1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2023 Loongson Technology Corporation Limited 4 */ 5 6 #include <drm/drm_managed.h> 7 8 #include "lsdc_drv.h" 9 #include "lsdc_output.h" 10 11 /* 12 * __lsdc_gpio_i2c_set - set the state of a gpio pin indicated by mask 13 * @mask: gpio pin mask 14 * @state: "0" for low, "1" for high 15 */ 16 static void __lsdc_gpio_i2c_set(struct lsdc_i2c * const li2c, int mask, int state) 17 { 18 struct lsdc_device *ldev = to_lsdc(li2c->ddev); 19 unsigned long flags; 20 u8 val; 21 22 spin_lock_irqsave(&ldev->reglock, flags); 23 24 if (state) { 25 /* 26 * Setting this pin as input directly, write 1 for input. 27 * The external pull-up resistor will pull the level up 28 */ 29 val = readb(li2c->dir_reg); 30 val |= mask; 31 writeb(val, li2c->dir_reg); 32 } else { 33 /* First set this pin as output, write 0 for output */ 34 val = readb(li2c->dir_reg); 35 val &= ~mask; 36 writeb(val, li2c->dir_reg); 37 38 /* Then, make this pin output 0 */ 39 val = readb(li2c->dat_reg); 40 val &= ~mask; 41 writeb(val, li2c->dat_reg); 42 } 43 44 spin_unlock_irqrestore(&ldev->reglock, flags); 45 } 46 47 /* 48 * __lsdc_gpio_i2c_get - read value back from the gpio pin indicated by mask 49 * @mask: gpio pin mask 50 * return "0" for low, "1" for high 51 */ 52 static int __lsdc_gpio_i2c_get(struct lsdc_i2c * const li2c, int mask) 53 { 54 struct lsdc_device *ldev = to_lsdc(li2c->ddev); 55 unsigned long flags; 56 u8 val; 57 58 spin_lock_irqsave(&ldev->reglock, flags); 59 60 /* First set this pin as input */ 61 val = readb(li2c->dir_reg); 62 val |= mask; 63 writeb(val, li2c->dir_reg); 64 65 /* Then get level state from this pin */ 66 val = readb(li2c->dat_reg); 67 68 spin_unlock_irqrestore(&ldev->reglock, flags); 69 70 return (val & mask) ? 1 : 0; 71 } 72 73 static void lsdc_gpio_i2c_set_sda(void *i2c, int state) 74 { 75 struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c; 76 /* set state on the li2c->sda pin */ 77 return __lsdc_gpio_i2c_set(li2c, li2c->sda, state); 78 } 79 80 static void lsdc_gpio_i2c_set_scl(void *i2c, int state) 81 { 82 struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c; 83 /* set state on the li2c->scl pin */ 84 return __lsdc_gpio_i2c_set(li2c, li2c->scl, state); 85 } 86 87 static int lsdc_gpio_i2c_get_sda(void *i2c) 88 { 89 struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c; 90 /* read value from the li2c->sda pin */ 91 return __lsdc_gpio_i2c_get(li2c, li2c->sda); 92 } 93 94 static int lsdc_gpio_i2c_get_scl(void *i2c) 95 { 96 struct lsdc_i2c * const li2c = (struct lsdc_i2c *)i2c; 97 /* read the value from the li2c->scl pin */ 98 return __lsdc_gpio_i2c_get(li2c, li2c->scl); 99 } 100 101 static void lsdc_destroy_i2c(struct drm_device *ddev, void *data) 102 { 103 struct lsdc_i2c *li2c = (struct lsdc_i2c *)data; 104 105 if (li2c) { 106 i2c_del_adapter(&li2c->adapter); 107 kfree(li2c); 108 } 109 } 110 111 /* 112 * The DC in ls7a1000/ls7a2000/ls2k2000 has builtin gpio hardware 113 * 114 * @reg_base: gpio reg base 115 * @index: output channel index, 0 for PIPE0, 1 for PIPE1 116 */ 117 int lsdc_create_i2c_chan(struct drm_device *ddev, 118 struct lsdc_display_pipe *dispipe, 119 unsigned int index) 120 { 121 struct lsdc_device *ldev = to_lsdc(ddev); 122 struct i2c_adapter *adapter; 123 struct lsdc_i2c *li2c; 124 int ret; 125 126 li2c = kzalloc(sizeof(*li2c), GFP_KERNEL); 127 if (!li2c) 128 return -ENOMEM; 129 130 dispipe->li2c = li2c; 131 132 if (index == 0) { 133 li2c->sda = 0x01; /* pin 0 */ 134 li2c->scl = 0x02; /* pin 1 */ 135 } else if (index == 1) { 136 li2c->sda = 0x04; /* pin 2 */ 137 li2c->scl = 0x08; /* pin 3 */ 138 } else { 139 return -ENOENT; 140 } 141 142 li2c->ddev = ddev; 143 li2c->dir_reg = ldev->reg_base + LS7A_DC_GPIO_DIR_REG; 144 li2c->dat_reg = ldev->reg_base + LS7A_DC_GPIO_DAT_REG; 145 146 li2c->bit.setsda = lsdc_gpio_i2c_set_sda; 147 li2c->bit.setscl = lsdc_gpio_i2c_set_scl; 148 li2c->bit.getsda = lsdc_gpio_i2c_get_sda; 149 li2c->bit.getscl = lsdc_gpio_i2c_get_scl; 150 li2c->bit.udelay = 5; 151 li2c->bit.timeout = usecs_to_jiffies(2200); 152 li2c->bit.data = li2c; 153 154 adapter = &li2c->adapter; 155 adapter->algo_data = &li2c->bit; 156 adapter->owner = THIS_MODULE; 157 adapter->dev.parent = ddev->dev; 158 adapter->nr = -1; 159 160 snprintf(adapter->name, sizeof(adapter->name), "lsdc-i2c%u", index); 161 162 i2c_set_adapdata(adapter, li2c); 163 164 ret = i2c_bit_add_bus(adapter); 165 if (ret) { 166 kfree(li2c); 167 return ret; 168 } 169 170 ret = drmm_add_action_or_reset(ddev, lsdc_destroy_i2c, li2c); 171 if (ret) 172 return ret; 173 174 drm_info(ddev, "%s(sda pin mask=%u, scl pin mask=%u) created\n", 175 adapter->name, li2c->sda, li2c->scl); 176 177 return 0; 178 } 179