// SPDX-License-Identifier: GPL-2.0-only /* * Driver for I2C adapter in Rockchip RK3xxx SoC * * Max Schwarz <[email protected]> * based on the patches by Rockchip Inc. */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/i2c.h> #include <linux/interrupt.h> #include <linux/iopoll.h> #include <linux/errno.h> #include <linux/err.h> #include <linux/platform_device.h> #include <linux/io.h> #include <linux/of_address.h> #include <linux/of_irq.h> #include <linux/spinlock.h> #include <linux/clk.h> #include <linux/wait.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> #include <linux/math64.h> /* Register Map */ #define REG_CON … #define REG_CLKDIV … #define REG_MRXADDR … #define REG_MRXRADDR … #define REG_MTXCNT … #define REG_MRXCNT … #define REG_IEN … #define REG_IPD … #define REG_FCNT … /* Data buffer offsets */ #define TXBUFFER_BASE … #define RXBUFFER_BASE … /* REG_CON bits */ #define REG_CON_EN … enum { … }; #define REG_CON_MOD(mod) … #define REG_CON_MOD_MASK … #define REG_CON_START … #define REG_CON_STOP … #define REG_CON_LASTACK … #define REG_CON_ACTACK … #define REG_CON_TUNING_MASK … #define REG_CON_SDA_CFG(cfg) … #define REG_CON_STA_CFG(cfg) … #define REG_CON_STO_CFG(cfg) … /* REG_MRXADDR bits */ #define REG_MRXADDR_VALID(x) … /* REG_IEN/REG_IPD bits */ #define REG_INT_BTF … #define REG_INT_BRF … #define REG_INT_MBTF … #define REG_INT_MBRF … #define REG_INT_START … #define REG_INT_STOP … #define REG_INT_NAKRCV … #define REG_INT_ALL … /* Constants */ #define WAIT_TIMEOUT … #define DEFAULT_SCL_RATE … /** * struct i2c_spec_values - I2C specification values for various modes * @min_hold_start_ns: min hold time (repeated) START condition * @min_low_ns: min LOW period of the SCL clock * @min_high_ns: min HIGH period of the SCL cloc * @min_setup_start_ns: min set-up time for a repeated START conditio * @max_data_hold_ns: max data hold time * @min_data_setup_ns: min data set-up time * @min_setup_stop_ns: min set-up time for STOP condition * @min_hold_buffer_ns: min bus free time between a STOP and * START condition */ struct i2c_spec_values { … }; static const struct i2c_spec_values standard_mode_spec = …; static const struct i2c_spec_values fast_mode_spec = …; static const struct i2c_spec_values fast_mode_plus_spec = …; /** * struct rk3x_i2c_calced_timings - calculated V1 timings * @div_low: Divider output for low * @div_high: Divider output for high * @tuning: Used to adjust setup/hold data time, * setup/hold start time and setup stop time for * v1's calc_timings, the tuning should all be 0 * for old hardware anyone using v0's calc_timings. */ struct rk3x_i2c_calced_timings { … }; enum rk3x_i2c_state { … }; /** * struct rk3x_i2c_soc_data - SOC-specific data * @grf_offset: offset inside the grf regmap for setting the i2c type * @calc_timings: Callback function for i2c timing information calculated */ struct rk3x_i2c_soc_data { … }; /** * struct rk3x_i2c - private data of the controller * @adap: corresponding I2C adapter * @dev: device for this controller * @soc_data: related soc data struct * @regs: virtual memory area * @clk: function clk for rk3399 or function & Bus clks for others * @pclk: Bus clk for rk3399 * @clk_rate_nb: i2c clk rate change notify * @irq: irq number * @t: I2C known timing information * @lock: spinlock for the i2c bus * @wait: the waitqueue to wait for i2c transfer * @busy: the condition for the event to wait for * @msg: current i2c message * @addr: addr of i2c target device * @mode: mode of i2c transfer * @is_last_msg: flag determines whether it is the last msg in this transfer * @state: state of i2c transfer * @processed: byte length which has been send or received * @error: error code for i2c transfer */ struct rk3x_i2c { … }; static inline void i2c_writel(struct rk3x_i2c *i2c, u32 value, unsigned int offset) { … } static inline u32 i2c_readl(struct rk3x_i2c *i2c, unsigned int offset) { … } /* Reset all interrupt pending bits */ static inline void rk3x_i2c_clean_ipd(struct rk3x_i2c *i2c) { … } /** * rk3x_i2c_start - Generate a START condition, which triggers a REG_INT_START interrupt. * @i2c: target controller data */ static void rk3x_i2c_start(struct rk3x_i2c *i2c) { … } /** * rk3x_i2c_stop - Generate a STOP condition, which triggers a REG_INT_STOP interrupt. * @i2c: target controller data * @error: Error code to return in rk3x_i2c_xfer */ static void rk3x_i2c_stop(struct rk3x_i2c *i2c, int error) { … } /** * rk3x_i2c_prepare_read - Setup a read according to i2c->msg * @i2c: target controller data */ static void rk3x_i2c_prepare_read(struct rk3x_i2c *i2c) { … } /** * rk3x_i2c_fill_transmit_buf - Fill the transmit buffer with data from i2c->msg * @i2c: target controller data */ static void rk3x_i2c_fill_transmit_buf(struct rk3x_i2c *i2c) { … } /* IRQ handlers for individual states */ static void rk3x_i2c_handle_start(struct rk3x_i2c *i2c, unsigned int ipd) { … } static void rk3x_i2c_handle_write(struct rk3x_i2c *i2c, unsigned int ipd) { … } static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, unsigned int ipd) { … } static void rk3x_i2c_handle_stop(struct rk3x_i2c *i2c, unsigned int ipd) { … } static irqreturn_t rk3x_i2c_irq(int irqno, void *dev_id) { … } /** * rk3x_i2c_get_spec - Get timing values of I2C specification * @speed: Desired SCL frequency * * Return: Matched i2c_spec_values. */ static const struct i2c_spec_values *rk3x_i2c_get_spec(unsigned int speed) { … } /** * rk3x_i2c_v0_calc_timings - Calculate divider values for desired SCL frequency * @clk_rate: I2C input clock rate * @t: Known I2C timing information * @t_calc: Caculated rk3x private timings that would be written into regs * * Return: %0 on success, -%EINVAL if the goal SCL rate is too slow. In that case * a best-effort divider value is returned in divs. If the target rate is * too high, we silently use the highest possible rate. */ static int rk3x_i2c_v0_calc_timings(unsigned long clk_rate, struct i2c_timings *t, struct rk3x_i2c_calced_timings *t_calc) { … } /** * rk3x_i2c_v1_calc_timings - Calculate timing values for desired SCL frequency * @clk_rate: I2C input clock rate * @t: Known I2C timing information * @t_calc: Caculated rk3x private timings that would be written into regs * * Return: %0 on success, -%EINVAL if the goal SCL rate is too slow. In that case * a best-effort divider value is returned in divs. If the target rate is * too high, we silently use the highest possible rate. * The following formulas are v1's method to calculate timings. * * l = divl + 1; * h = divh + 1; * s = sda_update_config + 1; * u = start_setup_config + 1; * p = stop_setup_config + 1; * T = Tclk_i2c; * * tHigh = 8 * h * T; * tLow = 8 * l * T; * * tHD;sda = (l * s + 1) * T; * tSU;sda = [(8 - s) * l + 1] * T; * tI2C = 8 * (l + h) * T; * * tSU;sta = (8h * u + 1) * T; * tHD;sta = [8h * (u + 1) - 1] * T; * tSU;sto = (8h * p + 1) * T; */ static int rk3x_i2c_v1_calc_timings(unsigned long clk_rate, struct i2c_timings *t, struct rk3x_i2c_calced_timings *t_calc) { … } static void rk3x_i2c_adapt_div(struct rk3x_i2c *i2c, unsigned long clk_rate) { … } /** * rk3x_i2c_clk_notifier_cb - Clock rate change callback * @nb: Pointer to notifier block * @event: Notification reason * @data: Pointer to notification data object * * The callback checks whether a valid bus frequency can be generated after the * change. If so, the change is acknowledged, otherwise the change is aborted. * New dividers are written to the HW in the pre- or post change notification * depending on the scaling direction. * * Code adapted from i2c-cadence.c. * * Return: NOTIFY_STOP if the rate change should be aborted, NOTIFY_OK * to acknowledge the change, NOTIFY_DONE if the notification is * considered irrelevant. */ static int rk3x_i2c_clk_notifier_cb(struct notifier_block *nb, unsigned long event, void *data) { … } /** * rk3x_i2c_setup - Setup I2C registers for an I2C operation specified by msgs, num. * @i2c: target controller data * @msgs: I2C msgs to process * @num: Number of msgs * * Must be called with i2c->lock held. * * Return: Number of I2C msgs processed or negative in case of error */ static int rk3x_i2c_setup(struct rk3x_i2c *i2c, struct i2c_msg *msgs, int num) { … } static int rk3x_i2c_wait_xfer_poll(struct rk3x_i2c *i2c) { … } static int rk3x_i2c_xfer_common(struct i2c_adapter *adap, struct i2c_msg *msgs, int num, bool polling) { … } static int rk3x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { … } static int rk3x_i2c_xfer_polling(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { … } static __maybe_unused int rk3x_i2c_resume(struct device *dev) { … } static u32 rk3x_i2c_func(struct i2c_adapter *adap) { … } static const struct i2c_algorithm rk3x_i2c_algorithm = …; static const struct rk3x_i2c_soc_data rv1108_soc_data = …; static const struct rk3x_i2c_soc_data rv1126_soc_data = …; static const struct rk3x_i2c_soc_data rk3066_soc_data = …; static const struct rk3x_i2c_soc_data rk3188_soc_data = …; static const struct rk3x_i2c_soc_data rk3228_soc_data = …; static const struct rk3x_i2c_soc_data rk3288_soc_data = …; static const struct rk3x_i2c_soc_data rk3399_soc_data = …; static const struct of_device_id rk3x_i2c_match[] = …; MODULE_DEVICE_TABLE(of, rk3x_i2c_match); static int rk3x_i2c_probe(struct platform_device *pdev) { … } static void rk3x_i2c_remove(struct platform_device *pdev) { … } static SIMPLE_DEV_PM_OPS(rk3x_i2c_pm_ops, NULL, rk3x_i2c_resume); static struct platform_driver rk3x_i2c_driver = …; module_platform_driver(…) …; MODULE_DESCRIPTION(…) …; MODULE_AUTHOR(…) …; MODULE_LICENSE(…) …;