1*607f2c00SIvan Vecera // SPDX-License-Identifier: GPL-2.0-only 2*607f2c00SIvan Vecera 3*607f2c00SIvan Vecera #include <linux/bitfield.h> 4*607f2c00SIvan Vecera #include <linux/cleanup.h> 5*607f2c00SIvan Vecera #include <linux/dev_printk.h> 6*607f2c00SIvan Vecera #include <linux/string.h> 7*607f2c00SIvan Vecera #include <linux/string_choices.h> 8*607f2c00SIvan Vecera #include <linux/types.h> 9*607f2c00SIvan Vecera 10*607f2c00SIvan Vecera #include "core.h" 11*607f2c00SIvan Vecera #include "ref.h" 12*607f2c00SIvan Vecera 13*607f2c00SIvan Vecera /** 14*607f2c00SIvan Vecera * zl3073x_ref_freq_factorize - factorize given frequency 15*607f2c00SIvan Vecera * @freq: input frequency 16*607f2c00SIvan Vecera * @base: base frequency 17*607f2c00SIvan Vecera * @mult: multiplier 18*607f2c00SIvan Vecera * 19*607f2c00SIvan Vecera * Checks if the given frequency can be factorized using one of the 20*607f2c00SIvan Vecera * supported base frequencies. If so the base frequency and multiplier 21*607f2c00SIvan Vecera * are stored into appropriate parameters if they are not NULL. 22*607f2c00SIvan Vecera * 23*607f2c00SIvan Vecera * Return: 0 on success, -EINVAL if the frequency cannot be factorized 24*607f2c00SIvan Vecera */ 25*607f2c00SIvan Vecera int 26*607f2c00SIvan Vecera zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult) 27*607f2c00SIvan Vecera { 28*607f2c00SIvan Vecera static const u16 base_freqs[] = { 29*607f2c00SIvan Vecera 1, 2, 4, 5, 8, 10, 16, 20, 25, 32, 40, 50, 64, 80, 100, 125, 30*607f2c00SIvan Vecera 128, 160, 200, 250, 256, 320, 400, 500, 625, 640, 800, 1000, 31*607f2c00SIvan Vecera 1250, 1280, 1600, 2000, 2500, 3125, 3200, 4000, 5000, 6250, 32*607f2c00SIvan Vecera 6400, 8000, 10000, 12500, 15625, 16000, 20000, 25000, 31250, 33*607f2c00SIvan Vecera 32000, 40000, 50000, 62500, 34*607f2c00SIvan Vecera }; 35*607f2c00SIvan Vecera u32 div; 36*607f2c00SIvan Vecera int i; 37*607f2c00SIvan Vecera 38*607f2c00SIvan Vecera for (i = 0; i < ARRAY_SIZE(base_freqs); i++) { 39*607f2c00SIvan Vecera div = freq / base_freqs[i]; 40*607f2c00SIvan Vecera 41*607f2c00SIvan Vecera if (div <= U16_MAX && (freq % base_freqs[i]) == 0) { 42*607f2c00SIvan Vecera if (base) 43*607f2c00SIvan Vecera *base = base_freqs[i]; 44*607f2c00SIvan Vecera if (mult) 45*607f2c00SIvan Vecera *mult = div; 46*607f2c00SIvan Vecera 47*607f2c00SIvan Vecera return 0; 48*607f2c00SIvan Vecera } 49*607f2c00SIvan Vecera } 50*607f2c00SIvan Vecera 51*607f2c00SIvan Vecera return -EINVAL; 52*607f2c00SIvan Vecera } 53*607f2c00SIvan Vecera 54*607f2c00SIvan Vecera /** 55*607f2c00SIvan Vecera * zl3073x_ref_state_fetch - fetch input reference state from hardware 56*607f2c00SIvan Vecera * @zldev: pointer to zl3073x_dev structure 57*607f2c00SIvan Vecera * @index: input reference index to fetch state for 58*607f2c00SIvan Vecera * 59*607f2c00SIvan Vecera * Function fetches state for the given input reference from hardware and 60*607f2c00SIvan Vecera * stores it for later use. 61*607f2c00SIvan Vecera * 62*607f2c00SIvan Vecera * Return: 0 on success, <0 on error 63*607f2c00SIvan Vecera */ 64*607f2c00SIvan Vecera int zl3073x_ref_state_fetch(struct zl3073x_dev *zldev, u8 index) 65*607f2c00SIvan Vecera { 66*607f2c00SIvan Vecera struct zl3073x_ref *ref = &zldev->ref[index]; 67*607f2c00SIvan Vecera int rc; 68*607f2c00SIvan Vecera 69*607f2c00SIvan Vecera /* For differential type inputs the N-pin reference shares 70*607f2c00SIvan Vecera * part of the configuration with the P-pin counterpart. 71*607f2c00SIvan Vecera */ 72*607f2c00SIvan Vecera if (zl3073x_is_n_pin(index) && zl3073x_ref_is_diff(ref - 1)) { 73*607f2c00SIvan Vecera struct zl3073x_ref *p_ref = &zldev->ref[index - 1]; 74*607f2c00SIvan Vecera 75*607f2c00SIvan Vecera /* Copy the shared items from the P-pin */ 76*607f2c00SIvan Vecera ref->config = p_ref->config; 77*607f2c00SIvan Vecera 78*607f2c00SIvan Vecera return 0; /* Finish - no non-shared items for now */ 79*607f2c00SIvan Vecera } 80*607f2c00SIvan Vecera 81*607f2c00SIvan Vecera guard(mutex)(&zldev->multiop_lock); 82*607f2c00SIvan Vecera 83*607f2c00SIvan Vecera /* Read reference configuration */ 84*607f2c00SIvan Vecera rc = zl3073x_mb_op(zldev, ZL_REG_REF_MB_SEM, ZL_REF_MB_SEM_RD, 85*607f2c00SIvan Vecera ZL_REG_REF_MB_MASK, BIT(index)); 86*607f2c00SIvan Vecera if (rc) 87*607f2c00SIvan Vecera return rc; 88*607f2c00SIvan Vecera 89*607f2c00SIvan Vecera /* Read ref_config register */ 90*607f2c00SIvan Vecera rc = zl3073x_read_u8(zldev, ZL_REG_REF_CONFIG, &ref->config); 91*607f2c00SIvan Vecera if (rc) 92*607f2c00SIvan Vecera return rc; 93*607f2c00SIvan Vecera 94*607f2c00SIvan Vecera dev_dbg(zldev->dev, "REF%u is %s and configured as %s\n", index, 95*607f2c00SIvan Vecera str_enabled_disabled(zl3073x_ref_is_enabled(ref)), 96*607f2c00SIvan Vecera zl3073x_ref_is_diff(ref) ? "differential" : "single-ended"); 97*607f2c00SIvan Vecera 98*607f2c00SIvan Vecera return rc; 99*607f2c00SIvan Vecera } 100*607f2c00SIvan Vecera 101*607f2c00SIvan Vecera /** 102*607f2c00SIvan Vecera * zl3073x_ref_state_get - get current input reference state 103*607f2c00SIvan Vecera * @zldev: pointer to zl3073x_dev structure 104*607f2c00SIvan Vecera * @index: input reference index to get state for 105*607f2c00SIvan Vecera * 106*607f2c00SIvan Vecera * Return: pointer to given input reference state 107*607f2c00SIvan Vecera */ 108*607f2c00SIvan Vecera const struct zl3073x_ref * 109*607f2c00SIvan Vecera zl3073x_ref_state_get(struct zl3073x_dev *zldev, u8 index) 110*607f2c00SIvan Vecera { 111*607f2c00SIvan Vecera return &zldev->ref[index]; 112*607f2c00SIvan Vecera } 113