Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
0004  * Copyright (C) 2017 Jonathan Liu <net147@gmail.com>
0005  */
0006 
0007 #include <linux/clk.h>
0008 #include <linux/i2c.h>
0009 #include <linux/iopoll.h>
0010 
0011 #include "sun4i_hdmi.h"
0012 
0013 #define SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK ( \
0014     SUN4I_HDMI_DDC_INT_STATUS_ILLEGAL_FIFO_OPERATION | \
0015     SUN4I_HDMI_DDC_INT_STATUS_DDC_RX_FIFO_UNDERFLOW | \
0016     SUN4I_HDMI_DDC_INT_STATUS_DDC_TX_FIFO_OVERFLOW | \
0017     SUN4I_HDMI_DDC_INT_STATUS_ARBITRATION_ERROR | \
0018     SUN4I_HDMI_DDC_INT_STATUS_ACK_ERROR | \
0019     SUN4I_HDMI_DDC_INT_STATUS_BUS_ERROR \
0020 )
0021 
0022 /* FIFO request bit is set when FIFO level is above RX_THRESHOLD during read */
0023 #define RX_THRESHOLD SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES_MAX
0024 
0025 static int fifo_transfer(struct sun4i_hdmi *hdmi, u8 *buf, int len, bool read)
0026 {
0027     /*
0028      * 1 byte takes 9 clock cycles (8 bits + 1 ACK) = 90 us for 100 kHz
0029      * clock. As clock rate is fixed, just round it up to 100 us.
0030      */
0031     const unsigned long byte_time_ns = 100;
0032     const u32 mask = SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK |
0033              SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST |
0034              SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE;
0035     u32 reg;
0036     /*
0037      * If threshold is inclusive, then the FIFO may only have
0038      * RX_THRESHOLD number of bytes, instead of RX_THRESHOLD + 1.
0039      */
0040     int read_len = RX_THRESHOLD +
0041         (hdmi->variant->ddc_fifo_thres_incl ? 0 : 1);
0042 
0043     /*
0044      * Limit transfer length by FIFO threshold or FIFO size.
0045      * For TX the threshold is for an empty FIFO.
0046      */
0047     len = min_t(int, len, read ? read_len : SUN4I_HDMI_DDC_FIFO_SIZE);
0048 
0049     /* Wait until error, FIFO request bit set or transfer complete */
0050     if (regmap_field_read_poll_timeout(hdmi->field_ddc_int_status, reg,
0051                        reg & mask, len * byte_time_ns,
0052                        100000))
0053         return -ETIMEDOUT;
0054 
0055     if (reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK)
0056         return -EIO;
0057 
0058     if (read)
0059         ioread8_rep(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len);
0060     else
0061         iowrite8_rep(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len);
0062 
0063     /* Clear FIFO request bit by forcing a write to that bit */
0064     regmap_field_force_write(hdmi->field_ddc_int_status,
0065                  SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST);
0066 
0067     return len;
0068 }
0069 
0070 static int xfer_msg(struct sun4i_hdmi *hdmi, struct i2c_msg *msg)
0071 {
0072     int i, len;
0073     u32 reg;
0074 
0075     /* Set FIFO direction */
0076     if (hdmi->variant->ddc_fifo_has_dir) {
0077         reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
0078         reg &= ~SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK;
0079         reg |= (msg->flags & I2C_M_RD) ?
0080                SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ :
0081                SUN4I_HDMI_DDC_CTRL_FIFO_DIR_WRITE;
0082         writel(reg, hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
0083     }
0084 
0085     /* Clear address register (not cleared by soft reset) */
0086     regmap_field_write(hdmi->field_ddc_addr_reg, 0);
0087 
0088     /* Set I2C address */
0089     regmap_field_write(hdmi->field_ddc_slave_addr, msg->addr);
0090 
0091     /*
0092      * Set FIFO RX/TX thresholds and clear FIFO
0093      *
0094      * If threshold is inclusive, we can set the TX threshold to
0095      * 0 instead of 1.
0096      */
0097     regmap_field_write(hdmi->field_ddc_fifo_tx_thres,
0098                hdmi->variant->ddc_fifo_thres_incl ? 0 : 1);
0099     regmap_field_write(hdmi->field_ddc_fifo_rx_thres, RX_THRESHOLD);
0100     regmap_field_write(hdmi->field_ddc_fifo_clear, 1);
0101     if (regmap_field_read_poll_timeout(hdmi->field_ddc_fifo_clear,
0102                        reg, !reg, 100, 2000))
0103         return -EIO;
0104 
0105     /* Set transfer length */
0106     regmap_field_write(hdmi->field_ddc_byte_count, msg->len);
0107 
0108     /* Set command */
0109     regmap_field_write(hdmi->field_ddc_cmd,
0110                msg->flags & I2C_M_RD ?
0111                SUN4I_HDMI_DDC_CMD_IMPLICIT_READ :
0112                SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE);
0113 
0114     /* Clear interrupt status bits by forcing a write */
0115     regmap_field_force_write(hdmi->field_ddc_int_status,
0116                  SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK |
0117                  SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST |
0118                  SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE);
0119 
0120     /* Start command */
0121     regmap_field_write(hdmi->field_ddc_start, 1);
0122 
0123     /* Transfer bytes */
0124     for (i = 0; i < msg->len; i += len) {
0125         len = fifo_transfer(hdmi, msg->buf + i, msg->len - i,
0126                     msg->flags & I2C_M_RD);
0127         if (len <= 0)
0128             return len;
0129     }
0130 
0131     /* Wait for command to finish */
0132     if (regmap_field_read_poll_timeout(hdmi->field_ddc_start,
0133                        reg, !reg, 100, 100000))
0134         return -EIO;
0135 
0136     /* Check for errors */
0137     regmap_field_read(hdmi->field_ddc_int_status, &reg);
0138     if ((reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK) ||
0139         !(reg & SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE)) {
0140         return -EIO;
0141     }
0142 
0143     return 0;
0144 }
0145 
0146 static int sun4i_hdmi_i2c_xfer(struct i2c_adapter *adap,
0147                    struct i2c_msg *msgs, int num)
0148 {
0149     struct sun4i_hdmi *hdmi = i2c_get_adapdata(adap);
0150     u32 reg;
0151     int err, i, ret = num;
0152 
0153     for (i = 0; i < num; i++) {
0154         if (!msgs[i].len)
0155             return -EINVAL;
0156         if (msgs[i].len > SUN4I_HDMI_DDC_BYTE_COUNT_MAX)
0157             return -EINVAL;
0158     }
0159 
0160     /* DDC clock needs to be enabled for the module to work */
0161     clk_prepare_enable(hdmi->ddc_clk);
0162     clk_set_rate(hdmi->ddc_clk, 100000);
0163 
0164     /* Reset I2C controller */
0165     regmap_field_write(hdmi->field_ddc_en, 1);
0166     regmap_field_write(hdmi->field_ddc_reset, 1);
0167     if (regmap_field_read_poll_timeout(hdmi->field_ddc_reset,
0168                        reg, !reg, 100, 2000)) {
0169         clk_disable_unprepare(hdmi->ddc_clk);
0170         return -EIO;
0171     }
0172 
0173     regmap_field_write(hdmi->field_ddc_sck_en, 1);
0174     regmap_field_write(hdmi->field_ddc_sda_en, 1);
0175 
0176     for (i = 0; i < num; i++) {
0177         err = xfer_msg(hdmi, &msgs[i]);
0178         if (err) {
0179             ret = err;
0180             break;
0181         }
0182     }
0183 
0184     clk_disable_unprepare(hdmi->ddc_clk);
0185     return ret;
0186 }
0187 
0188 static u32 sun4i_hdmi_i2c_func(struct i2c_adapter *adap)
0189 {
0190     return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
0191 }
0192 
0193 static const struct i2c_algorithm sun4i_hdmi_i2c_algorithm = {
0194     .master_xfer    = sun4i_hdmi_i2c_xfer,
0195     .functionality  = sun4i_hdmi_i2c_func,
0196 };
0197 
0198 static int sun4i_hdmi_init_regmap_fields(struct sun4i_hdmi *hdmi)
0199 {
0200     hdmi->field_ddc_en =
0201         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0202                     hdmi->variant->field_ddc_en);
0203     if (IS_ERR(hdmi->field_ddc_en))
0204         return PTR_ERR(hdmi->field_ddc_en);
0205 
0206     hdmi->field_ddc_start =
0207         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0208                     hdmi->variant->field_ddc_start);
0209     if (IS_ERR(hdmi->field_ddc_start))
0210         return PTR_ERR(hdmi->field_ddc_start);
0211 
0212     hdmi->field_ddc_reset =
0213         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0214                     hdmi->variant->field_ddc_reset);
0215     if (IS_ERR(hdmi->field_ddc_reset))
0216         return PTR_ERR(hdmi->field_ddc_reset);
0217 
0218     hdmi->field_ddc_addr_reg =
0219         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0220                     hdmi->variant->field_ddc_addr_reg);
0221     if (IS_ERR(hdmi->field_ddc_addr_reg))
0222         return PTR_ERR(hdmi->field_ddc_addr_reg);
0223 
0224     hdmi->field_ddc_slave_addr =
0225         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0226                     hdmi->variant->field_ddc_slave_addr);
0227     if (IS_ERR(hdmi->field_ddc_slave_addr))
0228         return PTR_ERR(hdmi->field_ddc_slave_addr);
0229 
0230     hdmi->field_ddc_int_mask =
0231         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0232                     hdmi->variant->field_ddc_int_mask);
0233     if (IS_ERR(hdmi->field_ddc_int_mask))
0234         return PTR_ERR(hdmi->field_ddc_int_mask);
0235 
0236     hdmi->field_ddc_int_status =
0237         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0238                     hdmi->variant->field_ddc_int_status);
0239     if (IS_ERR(hdmi->field_ddc_int_status))
0240         return PTR_ERR(hdmi->field_ddc_int_status);
0241 
0242     hdmi->field_ddc_fifo_clear =
0243         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0244                     hdmi->variant->field_ddc_fifo_clear);
0245     if (IS_ERR(hdmi->field_ddc_fifo_clear))
0246         return PTR_ERR(hdmi->field_ddc_fifo_clear);
0247 
0248     hdmi->field_ddc_fifo_rx_thres =
0249         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0250                     hdmi->variant->field_ddc_fifo_rx_thres);
0251     if (IS_ERR(hdmi->field_ddc_fifo_rx_thres))
0252         return PTR_ERR(hdmi->field_ddc_fifo_rx_thres);
0253 
0254     hdmi->field_ddc_fifo_tx_thres =
0255         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0256                     hdmi->variant->field_ddc_fifo_tx_thres);
0257     if (IS_ERR(hdmi->field_ddc_fifo_tx_thres))
0258         return PTR_ERR(hdmi->field_ddc_fifo_tx_thres);
0259 
0260     hdmi->field_ddc_byte_count =
0261         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0262                     hdmi->variant->field_ddc_byte_count);
0263     if (IS_ERR(hdmi->field_ddc_byte_count))
0264         return PTR_ERR(hdmi->field_ddc_byte_count);
0265 
0266     hdmi->field_ddc_cmd =
0267         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0268                     hdmi->variant->field_ddc_cmd);
0269     if (IS_ERR(hdmi->field_ddc_cmd))
0270         return PTR_ERR(hdmi->field_ddc_cmd);
0271 
0272     hdmi->field_ddc_sda_en =
0273         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0274                     hdmi->variant->field_ddc_sda_en);
0275     if (IS_ERR(hdmi->field_ddc_sda_en))
0276         return PTR_ERR(hdmi->field_ddc_sda_en);
0277 
0278     hdmi->field_ddc_sck_en =
0279         devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0280                     hdmi->variant->field_ddc_sck_en);
0281     if (IS_ERR(hdmi->field_ddc_sck_en))
0282         return PTR_ERR(hdmi->field_ddc_sck_en);
0283 
0284     return 0;
0285 }
0286 
0287 int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi)
0288 {
0289     struct i2c_adapter *adap;
0290     int ret = 0;
0291 
0292     ret = sun4i_ddc_create(hdmi, hdmi->ddc_parent_clk);
0293     if (ret)
0294         return ret;
0295 
0296     ret = sun4i_hdmi_init_regmap_fields(hdmi);
0297     if (ret)
0298         return ret;
0299 
0300     adap = devm_kzalloc(dev, sizeof(*adap), GFP_KERNEL);
0301     if (!adap)
0302         return -ENOMEM;
0303 
0304     adap->owner = THIS_MODULE;
0305     adap->class = I2C_CLASS_DDC;
0306     adap->algo = &sun4i_hdmi_i2c_algorithm;
0307     strlcpy(adap->name, "sun4i_hdmi_i2c adapter", sizeof(adap->name));
0308     i2c_set_adapdata(adap, hdmi);
0309 
0310     ret = i2c_add_adapter(adap);
0311     if (ret)
0312         return ret;
0313 
0314     hdmi->i2c = adap;
0315 
0316     return ret;
0317 }