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