^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for Silicon Labs Si570/Si571 Programmable XO/VCXO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2010, 2011 Ericsson AB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2011 Guenter Roeck.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2011 - 2013 Xilinx Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Author: Guenter Roeck <guenter.roeck@ericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Sören Brinkmann <soren.brinkmann@xilinx.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) /* Si570 registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define SI570_REG_HS_N1 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define SI570_REG_N1_RFREQ0 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define SI570_REG_RFREQ1 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define SI570_REG_RFREQ2 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define SI570_REG_RFREQ3 11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define SI570_REG_RFREQ4 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define SI570_REG_CONTROL 135
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define SI570_REG_FREEZE_DCO 137
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define SI570_DIV_OFFSET_7PPM 6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define HS_DIV_SHIFT 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define HS_DIV_MASK 0xe0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define HS_DIV_OFFSET 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define N1_6_2_MASK 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define N1_1_0_MASK 0xc0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define RFREQ_37_32_MASK 0x3f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define SI570_MIN_FREQ 10000000L
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define SI570_MAX_FREQ 1417500000L
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define SI598_MAX_FREQ 525000000L
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define FDCO_MIN 4850000000LL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define FDCO_MAX 5670000000LL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define SI570_CNTRL_RECALL (1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define SI570_CNTRL_FREEZE_M (1 << 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define SI570_CNTRL_NEWFREQ (1 << 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define SI570_FREEZE_DCO (1 << 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * struct clk_si570:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * @hw: Clock hw struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * @regmap: Device's regmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * @div_offset: Rgister offset for dividers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * @max_freq: Maximum frequency for this device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * @fxtal: Factory xtal frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * @n1: Clock divider N1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * @hs_div: Clock divider HSDIV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * @rfreq: Clock multiplier RFREQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * @frequency: Current output frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * @i2c_client: I2C client pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct clk_si570 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned int div_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u64 max_freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) u64 fxtal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) unsigned int n1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) unsigned int hs_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) u64 rfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) u64 frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct i2c_client *i2c_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define to_clk_si570(_hw) container_of(_hw, struct clk_si570, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) enum clk_si570_variant {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) si57x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) si59x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * si570_get_divs() - Read clock dividers from HW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * @data: Pointer to struct clk_si570
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * @rfreq: Fractional multiplier (output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * @n1: Divider N1 (output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * @hs_div: Divider HSDIV (output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * Returns 0 on success, negative errno otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * Retrieve clock dividers and multipliers from the HW.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int si570_get_divs(struct clk_si570 *data, u64 *rfreq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned int *n1, unsigned int *hs_div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) u8 reg[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) u64 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) err = regmap_bulk_read(data->regmap, SI570_REG_HS_N1 + data->div_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) reg, ARRAY_SIZE(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) *hs_div = ((reg[0] & HS_DIV_MASK) >> HS_DIV_SHIFT) + HS_DIV_OFFSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) *n1 = ((reg[0] & N1_6_2_MASK) << 2) + ((reg[1] & N1_1_0_MASK) >> 6) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* Handle invalid cases */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (*n1 > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) *n1 &= ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) tmp = reg[1] & RFREQ_37_32_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) tmp = (tmp << 8) + reg[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) tmp = (tmp << 8) + reg[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) tmp = (tmp << 8) + reg[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) tmp = (tmp << 8) + reg[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) *rfreq = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * si570_get_defaults() - Get default values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * @data: Driver data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * @fout: Factory frequency output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * Returns 0 on success, negative errno otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static int si570_get_defaults(struct clk_si570 *data, u64 fout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) u64 fdco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) regmap_write(data->regmap, SI570_REG_CONTROL, SI570_CNTRL_RECALL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) err = si570_get_divs(data, &data->rfreq, &data->n1, &data->hs_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * Accept optional precision loss to avoid arithmetic overflows.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * Acceptable per Silicon Labs Application Note AN334.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) fdco = fout * data->n1 * data->hs_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (fdco >= (1LL << 36))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) data->fxtal = div64_u64(fdco << 24, data->rfreq >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) data->fxtal = div64_u64(fdco << 28, data->rfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) data->frequency = fout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * si570_update_rfreq() - Update clock multiplier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * @data: Driver data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * Passes on regmap_bulk_write() return value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) static int si570_update_rfreq(struct clk_si570 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) u8 reg[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) reg[0] = ((data->n1 - 1) << 6) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ((data->rfreq >> 32) & RFREQ_37_32_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) reg[1] = (data->rfreq >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) reg[2] = (data->rfreq >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) reg[3] = (data->rfreq >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) reg[4] = data->rfreq & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return regmap_bulk_write(data->regmap, SI570_REG_N1_RFREQ0 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) data->div_offset, reg, ARRAY_SIZE(reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * si570_calc_divs() - Caluclate clock dividers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * @frequency: Target frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * @data: Driver data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * @out_rfreq: RFREG fractional multiplier (output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * @out_n1: Clock divider N1 (output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * @out_hs_div: Clock divider HSDIV (output)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * Returns 0 on success, negative errno otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * Calculate the clock dividers (@out_hs_div, @out_n1) and clock multiplier
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * (@out_rfreq) for a given target @frequency.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static int si570_calc_divs(unsigned long frequency, struct clk_si570 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) u64 *out_rfreq, unsigned int *out_n1, unsigned int *out_hs_div)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) unsigned int n1, hs_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) u64 fdco, best_fdco = ULLONG_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static const uint8_t si570_hs_div_values[] = { 11, 9, 7, 6, 5, 4 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) for (i = 0; i < ARRAY_SIZE(si570_hs_div_values); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) hs_div = si570_hs_div_values[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* Calculate lowest possible value for n1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) n1 = div_u64(div_u64(FDCO_MIN, hs_div), frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (!n1 || (n1 & 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) n1++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) while (n1 <= 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) fdco = (u64)frequency * (u64)hs_div * (u64)n1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (fdco > FDCO_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (fdco >= FDCO_MIN && fdco < best_fdco) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) *out_n1 = n1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) *out_hs_div = hs_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) *out_rfreq = div64_u64(fdco << 28, data->fxtal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) best_fdco = fdco;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) n1 += (n1 == 1 ? 1 : 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (best_fdco == ULLONG_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static unsigned long si570_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) u64 rfreq, rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) unsigned int n1, hs_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct clk_si570 *data = to_clk_si570(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) err = si570_get_divs(data, &rfreq, &n1, &hs_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) dev_err(&data->i2c_client->dev, "unable to recalc rate\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) return data->frequency;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) rfreq = div_u64(rfreq, hs_div * n1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) rate = (data->fxtal * rfreq) >> 28;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) static long si570_round_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) unsigned long *parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) u64 rfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) unsigned int n1, hs_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct clk_si570 *data = to_clk_si570(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (!rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) if (div64_u64(abs(rate - data->frequency) * 10000LL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) data->frequency) < 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) rfreq = div64_u64((data->rfreq * rate) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) div64_u64(data->frequency, 2), data->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) n1 = data->n1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) hs_div = data->hs_div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) err = si570_calc_divs(rate, data, &rfreq, &n1, &hs_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) dev_err(&data->i2c_client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) "unable to round rate\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * si570_set_frequency() - Adjust output frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * @data: Driver data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * @frequency: Target frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * Returns 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * Update output frequency for big frequency changes (> 3,500 ppm).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static int si570_set_frequency(struct clk_si570 *data, unsigned long frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) err = si570_calc_divs(frequency, data, &data->rfreq, &data->n1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) &data->hs_div);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * The DCO reg should be accessed with a read-modify-write operation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * per AN334
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) regmap_write(data->regmap, SI570_REG_FREEZE_DCO, SI570_FREEZE_DCO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) regmap_write(data->regmap, SI570_REG_HS_N1 + data->div_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) ((data->hs_div - HS_DIV_OFFSET) << HS_DIV_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) (((data->n1 - 1) >> 2) & N1_6_2_MASK));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) si570_update_rfreq(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) regmap_write(data->regmap, SI570_REG_FREEZE_DCO, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) regmap_write(data->regmap, SI570_REG_CONTROL, SI570_CNTRL_NEWFREQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /* Applying a new frequency can take up to 10ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) usleep_range(10000, 12000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * si570_set_frequency_small() - Adjust output frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * @data: Driver data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * @frequency: Target frequency
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * Returns 0 on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * Update output frequency for small frequency changes (< 3,500 ppm).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static int si570_set_frequency_small(struct clk_si570 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) unsigned long frequency)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * This is a re-implementation of DIV_ROUND_CLOSEST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * using the div64_u64 function lieu of letting the compiler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * insert EABI calls
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) data->rfreq = div64_u64((data->rfreq * frequency) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) div_u64(data->frequency, 2), data->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) regmap_write(data->regmap, SI570_REG_CONTROL, SI570_CNTRL_FREEZE_M);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) si570_update_rfreq(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) regmap_write(data->regmap, SI570_REG_CONTROL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) /* Applying a new frequency (small change) can take up to 100us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) usleep_range(100, 200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static int si570_set_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct clk_si570 *data = to_clk_si570(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct i2c_client *client = data->i2c_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (rate < SI570_MIN_FREQ || rate > data->max_freq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) "requested frequency %lu Hz is out of range\n", rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (div64_u64(abs(rate - data->frequency) * 10000LL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) data->frequency) < 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) err = si570_set_frequency_small(data, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) err = si570_set_frequency(data, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) data->frequency = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static const struct clk_ops si570_clk_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) .recalc_rate = si570_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) .round_rate = si570_round_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) .set_rate = si570_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static bool si570_regmap_is_volatile(struct device *dev, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) case SI570_REG_CONTROL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static bool si570_regmap_is_writeable(struct device *dev, unsigned int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) switch (reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) case SI570_REG_HS_N1 ... (SI570_REG_RFREQ4 + SI570_DIV_OFFSET_7PPM):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) case SI570_REG_CONTROL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) case SI570_REG_FREEZE_DCO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static const struct regmap_config si570_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) .reg_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) .val_bits = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) .cache_type = REGCACHE_RBTREE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) .max_register = 137,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) .writeable_reg = si570_regmap_is_writeable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) .volatile_reg = si570_regmap_is_volatile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static int si570_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct clk_si570 *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) u32 initial_fout, factory_fout, stability;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) enum clk_si570_variant variant = id->driver_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) init.ops = &si570_clk_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) init.num_parents = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) data->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) data->i2c_client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (variant == si57x) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) err = of_property_read_u32(client->dev.of_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) "temperature-stability", &stability);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) "'temperature-stability' property missing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* adjust register offsets for 7ppm devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (stability == 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) data->div_offset = SI570_DIV_OFFSET_7PPM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) data->max_freq = SI570_MAX_FREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) data->max_freq = SI598_MAX_FREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (of_property_read_string(client->dev.of_node, "clock-output-names",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) &init.name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) init.name = client->dev.of_node->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) err = of_property_read_u32(client->dev.of_node, "factory-fout",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) &factory_fout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) dev_err(&client->dev, "'factory-fout' property missing\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) data->regmap = devm_regmap_init_i2c(client, &si570_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (IS_ERR(data->regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) dev_err(&client->dev, "failed to allocate register map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return PTR_ERR(data->regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) i2c_set_clientdata(client, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) err = si570_get_defaults(data, factory_fout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) err = devm_clk_hw_register(&client->dev, &data->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) dev_err(&client->dev, "clock registration failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) err = of_clk_add_hw_provider(client->dev.of_node, of_clk_hw_simple_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) &data->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) dev_err(&client->dev, "unable to add clk provider\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) /* Read the requested initial output frequency from device tree */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (!of_property_read_u32(client->dev.of_node, "clock-frequency",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) &initial_fout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) err = clk_set_rate(data->hw.clk, initial_fout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) of_clk_del_provider(client->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) /* Display a message indicating that we've successfully registered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) dev_info(&client->dev, "registered, current frequency %llu Hz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) data->frequency);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) static int si570_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) of_clk_del_provider(client->dev.of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) static const struct i2c_device_id si570_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) { "si570", si57x },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) { "si571", si57x },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) { "si598", si59x },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) { "si599", si59x },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) MODULE_DEVICE_TABLE(i2c, si570_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) static const struct of_device_id clk_si570_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) { .compatible = "silabs,si570" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) { .compatible = "silabs,si571" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) { .compatible = "silabs,si598" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) { .compatible = "silabs,si599" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) MODULE_DEVICE_TABLE(of, clk_si570_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) static struct i2c_driver si570_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) .name = "si570",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) .of_match_table = clk_si570_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) .probe = si570_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) .remove = si570_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) .id_table = si570_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) module_i2c_driver(si570_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) MODULE_AUTHOR("Soeren Brinkmann <soren.brinkmann@xilinx.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) MODULE_DESCRIPTION("Si570 driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) MODULE_LICENSE("GPL");