1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/component.h> 4 #include <linux/iopoll.h> 5 #include <linux/of.h> 6 #include <linux/platform_device.h> 7 8 #include <drm/drm_bridge.h> 9 #include <drm/drm_mipi_dsi.h> 10 11 #define DSI_GEN_HDR 0x6c 12 #define DSI_GEN_PLD_DATA 0x70 13 14 #define DSI_CMD_PKT_STATUS 0x74 15 16 #define GEN_PLD_R_EMPTY BIT(4) 17 #define GEN_PLD_W_FULL BIT(3) 18 #define GEN_PLD_W_EMPTY BIT(2) 19 #define GEN_CMD_FULL BIT(1) 20 #define GEN_CMD_EMPTY BIT(0) 21 #define GEN_RD_CMD_BUSY BIT(6) 22 #define CMD_PKT_STATUS_TIMEOUT_US 20000 23 24 struct adp_mipi_drv_private { 25 struct mipi_dsi_host dsi; 26 struct drm_bridge bridge; 27 struct drm_bridge *next_bridge; 28 void __iomem *mipi; 29 }; 30 31 #define mipi_to_adp(x) container_of(x, struct adp_mipi_drv_private, dsi) 32 33 static int adp_dsi_gen_pkt_hdr_write(struct adp_mipi_drv_private *adp, u32 hdr_val) 34 { 35 int ret; 36 u32 val, mask; 37 38 ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS, 39 val, !(val & GEN_CMD_FULL), 1000, 40 CMD_PKT_STATUS_TIMEOUT_US); 41 if (ret) { 42 dev_err(adp->dsi.dev, "failed to get available command FIFO\n"); 43 return ret; 44 } 45 46 writel(hdr_val, adp->mipi + DSI_GEN_HDR); 47 48 mask = GEN_CMD_EMPTY | GEN_PLD_W_EMPTY; 49 ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS, 50 val, (val & mask) == mask, 51 1000, CMD_PKT_STATUS_TIMEOUT_US); 52 if (ret) { 53 dev_err(adp->dsi.dev, "failed to write command FIFO\n"); 54 return ret; 55 } 56 57 return 0; 58 } 59 60 static int adp_dsi_write(struct adp_mipi_drv_private *adp, 61 const struct mipi_dsi_packet *packet) 62 { 63 const u8 *tx_buf = packet->payload; 64 int len = packet->payload_length, pld_data_bytes = sizeof(u32), ret; 65 __le32 word; 66 u32 val; 67 68 while (len) { 69 if (len < pld_data_bytes) { 70 word = 0; 71 memcpy(&word, tx_buf, len); 72 writel(le32_to_cpu(word), adp->mipi + DSI_GEN_PLD_DATA); 73 len = 0; 74 } else { 75 memcpy(&word, tx_buf, pld_data_bytes); 76 writel(le32_to_cpu(word), adp->mipi + DSI_GEN_PLD_DATA); 77 tx_buf += pld_data_bytes; 78 len -= pld_data_bytes; 79 } 80 81 ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS, 82 val, !(val & GEN_PLD_W_FULL), 1000, 83 CMD_PKT_STATUS_TIMEOUT_US); 84 if (ret) { 85 dev_err(adp->dsi.dev, 86 "failed to get available write payload FIFO\n"); 87 return ret; 88 } 89 } 90 91 word = 0; 92 memcpy(&word, packet->header, sizeof(packet->header)); 93 return adp_dsi_gen_pkt_hdr_write(adp, le32_to_cpu(word)); 94 } 95 96 static int adp_dsi_read(struct adp_mipi_drv_private *adp, 97 const struct mipi_dsi_msg *msg) 98 { 99 int i, j, ret, len = msg->rx_len; 100 u8 *buf = msg->rx_buf; 101 u32 val; 102 103 /* Wait end of the read operation */ 104 ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS, 105 val, !(val & GEN_RD_CMD_BUSY), 106 1000, CMD_PKT_STATUS_TIMEOUT_US); 107 if (ret) { 108 dev_err(adp->dsi.dev, "Timeout during read operation\n"); 109 return ret; 110 } 111 112 for (i = 0; i < len; i += 4) { 113 /* Read fifo must not be empty before all bytes are read */ 114 ret = readl_poll_timeout(adp->mipi + DSI_CMD_PKT_STATUS, 115 val, !(val & GEN_PLD_R_EMPTY), 116 1000, CMD_PKT_STATUS_TIMEOUT_US); 117 if (ret) { 118 dev_err(adp->dsi.dev, "Read payload FIFO is empty\n"); 119 return ret; 120 } 121 122 val = readl(adp->mipi + DSI_GEN_PLD_DATA); 123 for (j = 0; j < 4 && j + i < len; j++) 124 buf[i + j] = val >> (8 * j); 125 } 126 127 return ret; 128 } 129 130 static ssize_t adp_dsi_host_transfer(struct mipi_dsi_host *host, 131 const struct mipi_dsi_msg *msg) 132 { 133 struct adp_mipi_drv_private *adp = mipi_to_adp(host); 134 struct mipi_dsi_packet packet; 135 int ret, nb_bytes; 136 137 ret = mipi_dsi_create_packet(&packet, msg); 138 if (ret) { 139 dev_err(adp->dsi.dev, "failed to create packet: %d\n", ret); 140 return ret; 141 } 142 143 ret = adp_dsi_write(adp, &packet); 144 if (ret) 145 return ret; 146 147 if (msg->rx_buf && msg->rx_len) { 148 ret = adp_dsi_read(adp, msg); 149 if (ret) 150 return ret; 151 nb_bytes = msg->rx_len; 152 } else { 153 nb_bytes = packet.size; 154 } 155 156 return nb_bytes; 157 } 158 159 static int adp_dsi_bind(struct device *dev, struct device *master, void *data) 160 { 161 return 0; 162 } 163 164 static void adp_dsi_unbind(struct device *dev, struct device *master, void *data) 165 { 166 } 167 168 static const struct component_ops adp_dsi_component_ops = { 169 .bind = adp_dsi_bind, 170 .unbind = adp_dsi_unbind, 171 }; 172 173 static int adp_dsi_host_attach(struct mipi_dsi_host *host, 174 struct mipi_dsi_device *dev) 175 { 176 struct adp_mipi_drv_private *adp = mipi_to_adp(host); 177 struct drm_bridge *next; 178 int ret; 179 180 next = devm_drm_of_get_bridge(adp->dsi.dev, adp->dsi.dev->of_node, 1, 0); 181 if (IS_ERR(next)) 182 return PTR_ERR(next); 183 184 adp->next_bridge = next; 185 186 drm_bridge_add(&adp->bridge); 187 188 ret = component_add(host->dev, &adp_dsi_component_ops); 189 if (ret) { 190 pr_err("failed to add dsi_host component: %d\n", ret); 191 drm_bridge_remove(&adp->bridge); 192 return ret; 193 } 194 195 return 0; 196 } 197 198 static int adp_dsi_host_detach(struct mipi_dsi_host *host, 199 struct mipi_dsi_device *dev) 200 { 201 struct adp_mipi_drv_private *adp = mipi_to_adp(host); 202 203 component_del(host->dev, &adp_dsi_component_ops); 204 drm_bridge_remove(&adp->bridge); 205 return 0; 206 } 207 208 static const struct mipi_dsi_host_ops adp_dsi_host_ops = { 209 .transfer = adp_dsi_host_transfer, 210 .attach = adp_dsi_host_attach, 211 .detach = adp_dsi_host_detach, 212 }; 213 214 static int adp_dsi_bridge_attach(struct drm_bridge *bridge, 215 enum drm_bridge_attach_flags flags) 216 { 217 struct adp_mipi_drv_private *adp = 218 container_of(bridge, struct adp_mipi_drv_private, bridge); 219 220 return drm_bridge_attach(bridge->encoder, adp->next_bridge, bridge, flags); 221 } 222 223 static const struct drm_bridge_funcs adp_dsi_bridge_funcs = { 224 .attach = adp_dsi_bridge_attach, 225 }; 226 227 static int adp_mipi_probe(struct platform_device *pdev) 228 { 229 struct adp_mipi_drv_private *adp; 230 231 adp = devm_kzalloc(&pdev->dev, sizeof(*adp), GFP_KERNEL); 232 if (!adp) 233 return -ENOMEM; 234 235 adp->mipi = devm_platform_ioremap_resource(pdev, 0); 236 if (IS_ERR(adp->mipi)) { 237 dev_err(&pdev->dev, "failed to map mipi mmio"); 238 return PTR_ERR(adp->mipi); 239 } 240 241 adp->dsi.dev = &pdev->dev; 242 adp->dsi.ops = &adp_dsi_host_ops; 243 adp->bridge.funcs = &adp_dsi_bridge_funcs; 244 adp->bridge.of_node = pdev->dev.of_node; 245 adp->bridge.type = DRM_MODE_CONNECTOR_DSI; 246 dev_set_drvdata(&pdev->dev, adp); 247 return mipi_dsi_host_register(&adp->dsi); 248 } 249 250 static void adp_mipi_remove(struct platform_device *pdev) 251 { 252 struct device *dev = &pdev->dev; 253 struct adp_mipi_drv_private *adp = dev_get_drvdata(dev); 254 255 mipi_dsi_host_unregister(&adp->dsi); 256 } 257 258 static const struct of_device_id adp_mipi_of_match[] = { 259 { .compatible = "apple,h7-display-pipe-mipi", }, 260 { }, 261 }; 262 MODULE_DEVICE_TABLE(of, adp_mipi_of_match); 263 264 static struct platform_driver adp_mipi_platform_driver = { 265 .driver = { 266 .name = "adp-mipi", 267 .of_match_table = adp_mipi_of_match, 268 }, 269 .probe = adp_mipi_probe, 270 .remove = adp_mipi_remove, 271 }; 272 273 module_platform_driver(adp_mipi_platform_driver); 274 275 MODULE_DESCRIPTION("Apple Display Pipe MIPI driver"); 276 MODULE_LICENSE("GPL"); 277