1*471a92f8SSasha Finkelstein // SPDX-License-Identifier: GPL-2.0 2*471a92f8SSasha Finkelstein /* 3*471a92f8SSasha Finkelstein * Apple Z2 touchscreen driver 4*471a92f8SSasha Finkelstein * 5*471a92f8SSasha Finkelstein * Copyright (C) The Asahi Linux Contributors 6*471a92f8SSasha Finkelstein */ 7*471a92f8SSasha Finkelstein 8*471a92f8SSasha Finkelstein #include <linux/delay.h> 9*471a92f8SSasha Finkelstein #include <linux/firmware.h> 10*471a92f8SSasha Finkelstein #include <linux/input.h> 11*471a92f8SSasha Finkelstein #include <linux/input/mt.h> 12*471a92f8SSasha Finkelstein #include <linux/input/touchscreen.h> 13*471a92f8SSasha Finkelstein #include <linux/interrupt.h> 14*471a92f8SSasha Finkelstein #include <linux/module.h> 15*471a92f8SSasha Finkelstein #include <linux/of.h> 16*471a92f8SSasha Finkelstein #include <linux/spi/spi.h> 17*471a92f8SSasha Finkelstein #include <linux/unaligned.h> 18*471a92f8SSasha Finkelstein 19*471a92f8SSasha Finkelstein #define APPLE_Z2_NUM_FINGERS_OFFSET 16 20*471a92f8SSasha Finkelstein #define APPLE_Z2_FINGERS_OFFSET 24 21*471a92f8SSasha Finkelstein #define APPLE_Z2_TOUCH_STARTED 3 22*471a92f8SSasha Finkelstein #define APPLE_Z2_TOUCH_MOVED 4 23*471a92f8SSasha Finkelstein #define APPLE_Z2_CMD_READ_INTERRUPT_DATA 0xEB 24*471a92f8SSasha Finkelstein #define APPLE_Z2_HBPP_CMD_BLOB 0x3001 25*471a92f8SSasha Finkelstein #define APPLE_Z2_FW_MAGIC 0x5746325A 26*471a92f8SSasha Finkelstein #define LOAD_COMMAND_INIT_PAYLOAD 0 27*471a92f8SSasha Finkelstein #define LOAD_COMMAND_SEND_BLOB 1 28*471a92f8SSasha Finkelstein #define LOAD_COMMAND_SEND_CALIBRATION 2 29*471a92f8SSasha Finkelstein #define CAL_PROP_NAME "apple,z2-cal-blob" 30*471a92f8SSasha Finkelstein 31*471a92f8SSasha Finkelstein struct apple_z2 { 32*471a92f8SSasha Finkelstein struct spi_device *spidev; 33*471a92f8SSasha Finkelstein struct gpio_desc *reset_gpio; 34*471a92f8SSasha Finkelstein struct input_dev *input_dev; 35*471a92f8SSasha Finkelstein struct completion boot_irq; 36*471a92f8SSasha Finkelstein bool booted; 37*471a92f8SSasha Finkelstein int index_parity; 38*471a92f8SSasha Finkelstein struct touchscreen_properties props; 39*471a92f8SSasha Finkelstein const char *fw_name; 40*471a92f8SSasha Finkelstein u8 *tx_buf; 41*471a92f8SSasha Finkelstein u8 *rx_buf; 42*471a92f8SSasha Finkelstein }; 43*471a92f8SSasha Finkelstein 44*471a92f8SSasha Finkelstein struct apple_z2_finger { 45*471a92f8SSasha Finkelstein u8 finger; 46*471a92f8SSasha Finkelstein u8 state; 47*471a92f8SSasha Finkelstein __le16 unknown2; 48*471a92f8SSasha Finkelstein __le16 abs_x; 49*471a92f8SSasha Finkelstein __le16 abs_y; 50*471a92f8SSasha Finkelstein __le16 rel_x; 51*471a92f8SSasha Finkelstein __le16 rel_y; 52*471a92f8SSasha Finkelstein __le16 tool_major; 53*471a92f8SSasha Finkelstein __le16 tool_minor; 54*471a92f8SSasha Finkelstein __le16 orientation; 55*471a92f8SSasha Finkelstein __le16 touch_major; 56*471a92f8SSasha Finkelstein __le16 touch_minor; 57*471a92f8SSasha Finkelstein __le16 unused[2]; 58*471a92f8SSasha Finkelstein __le16 pressure; 59*471a92f8SSasha Finkelstein __le16 multi; 60*471a92f8SSasha Finkelstein } __packed; 61*471a92f8SSasha Finkelstein 62*471a92f8SSasha Finkelstein struct apple_z2_hbpp_blob_hdr { 63*471a92f8SSasha Finkelstein __le16 cmd; 64*471a92f8SSasha Finkelstein __le16 len; 65*471a92f8SSasha Finkelstein __le32 addr; 66*471a92f8SSasha Finkelstein __le16 checksum; 67*471a92f8SSasha Finkelstein }; 68*471a92f8SSasha Finkelstein 69*471a92f8SSasha Finkelstein struct apple_z2_fw_hdr { 70*471a92f8SSasha Finkelstein __le32 magic; 71*471a92f8SSasha Finkelstein __le32 version; 72*471a92f8SSasha Finkelstein }; 73*471a92f8SSasha Finkelstein 74*471a92f8SSasha Finkelstein struct apple_z2_read_interrupt_cmd { 75*471a92f8SSasha Finkelstein u8 cmd; 76*471a92f8SSasha Finkelstein u8 counter; 77*471a92f8SSasha Finkelstein u8 unused[12]; 78*471a92f8SSasha Finkelstein __le16 checksum; 79*471a92f8SSasha Finkelstein }; 80*471a92f8SSasha Finkelstein 81*471a92f8SSasha Finkelstein static void apple_z2_parse_touches(struct apple_z2 *z2, 82*471a92f8SSasha Finkelstein const u8 *msg, size_t msg_len) 83*471a92f8SSasha Finkelstein { 84*471a92f8SSasha Finkelstein int i; 85*471a92f8SSasha Finkelstein int nfingers; 86*471a92f8SSasha Finkelstein int slot; 87*471a92f8SSasha Finkelstein int slot_valid; 88*471a92f8SSasha Finkelstein struct apple_z2_finger *fingers; 89*471a92f8SSasha Finkelstein 90*471a92f8SSasha Finkelstein if (msg_len <= APPLE_Z2_NUM_FINGERS_OFFSET) 91*471a92f8SSasha Finkelstein return; 92*471a92f8SSasha Finkelstein nfingers = msg[APPLE_Z2_NUM_FINGERS_OFFSET]; 93*471a92f8SSasha Finkelstein fingers = (struct apple_z2_finger *)(msg + APPLE_Z2_FINGERS_OFFSET); 94*471a92f8SSasha Finkelstein for (i = 0; i < nfingers; i++) { 95*471a92f8SSasha Finkelstein slot = input_mt_get_slot_by_key(z2->input_dev, fingers[i].finger); 96*471a92f8SSasha Finkelstein if (slot < 0) { 97*471a92f8SSasha Finkelstein dev_warn(&z2->spidev->dev, "unable to get slot for finger\n"); 98*471a92f8SSasha Finkelstein continue; 99*471a92f8SSasha Finkelstein } 100*471a92f8SSasha Finkelstein slot_valid = fingers[i].state == APPLE_Z2_TOUCH_STARTED || 101*471a92f8SSasha Finkelstein fingers[i].state == APPLE_Z2_TOUCH_MOVED; 102*471a92f8SSasha Finkelstein input_mt_slot(z2->input_dev, slot); 103*471a92f8SSasha Finkelstein if (!input_mt_report_slot_state(z2->input_dev, MT_TOOL_FINGER, slot_valid)) 104*471a92f8SSasha Finkelstein continue; 105*471a92f8SSasha Finkelstein touchscreen_report_pos(z2->input_dev, &z2->props, 106*471a92f8SSasha Finkelstein le16_to_cpu(fingers[i].abs_x), 107*471a92f8SSasha Finkelstein le16_to_cpu(fingers[i].abs_y), 108*471a92f8SSasha Finkelstein true); 109*471a92f8SSasha Finkelstein input_report_abs(z2->input_dev, ABS_MT_WIDTH_MAJOR, 110*471a92f8SSasha Finkelstein le16_to_cpu(fingers[i].tool_major)); 111*471a92f8SSasha Finkelstein input_report_abs(z2->input_dev, ABS_MT_WIDTH_MINOR, 112*471a92f8SSasha Finkelstein le16_to_cpu(fingers[i].tool_minor)); 113*471a92f8SSasha Finkelstein input_report_abs(z2->input_dev, ABS_MT_ORIENTATION, 114*471a92f8SSasha Finkelstein le16_to_cpu(fingers[i].orientation)); 115*471a92f8SSasha Finkelstein input_report_abs(z2->input_dev, ABS_MT_TOUCH_MAJOR, 116*471a92f8SSasha Finkelstein le16_to_cpu(fingers[i].touch_major)); 117*471a92f8SSasha Finkelstein input_report_abs(z2->input_dev, ABS_MT_TOUCH_MINOR, 118*471a92f8SSasha Finkelstein le16_to_cpu(fingers[i].touch_minor)); 119*471a92f8SSasha Finkelstein } 120*471a92f8SSasha Finkelstein input_mt_sync_frame(z2->input_dev); 121*471a92f8SSasha Finkelstein input_sync(z2->input_dev); 122*471a92f8SSasha Finkelstein } 123*471a92f8SSasha Finkelstein 124*471a92f8SSasha Finkelstein static int apple_z2_read_packet(struct apple_z2 *z2) 125*471a92f8SSasha Finkelstein { 126*471a92f8SSasha Finkelstein struct apple_z2_read_interrupt_cmd *len_cmd = (void *)z2->tx_buf; 127*471a92f8SSasha Finkelstein struct spi_transfer xfer; 128*471a92f8SSasha Finkelstein int error; 129*471a92f8SSasha Finkelstein size_t pkt_len; 130*471a92f8SSasha Finkelstein 131*471a92f8SSasha Finkelstein memset(&xfer, 0, sizeof(xfer)); 132*471a92f8SSasha Finkelstein len_cmd->cmd = APPLE_Z2_CMD_READ_INTERRUPT_DATA; 133*471a92f8SSasha Finkelstein len_cmd->counter = z2->index_parity + 1; 134*471a92f8SSasha Finkelstein len_cmd->checksum = 135*471a92f8SSasha Finkelstein cpu_to_le16(APPLE_Z2_CMD_READ_INTERRUPT_DATA + len_cmd->counter); 136*471a92f8SSasha Finkelstein z2->index_parity = !z2->index_parity; 137*471a92f8SSasha Finkelstein xfer.tx_buf = z2->tx_buf; 138*471a92f8SSasha Finkelstein xfer.rx_buf = z2->rx_buf; 139*471a92f8SSasha Finkelstein xfer.len = sizeof(*len_cmd); 140*471a92f8SSasha Finkelstein 141*471a92f8SSasha Finkelstein error = spi_sync_transfer(z2->spidev, &xfer, 1); 142*471a92f8SSasha Finkelstein if (error) 143*471a92f8SSasha Finkelstein return error; 144*471a92f8SSasha Finkelstein 145*471a92f8SSasha Finkelstein pkt_len = (get_unaligned_le16(z2->rx_buf + 1) + 8) & 0xfffffffc; 146*471a92f8SSasha Finkelstein 147*471a92f8SSasha Finkelstein error = spi_read(z2->spidev, z2->rx_buf, pkt_len); 148*471a92f8SSasha Finkelstein if (error) 149*471a92f8SSasha Finkelstein return error; 150*471a92f8SSasha Finkelstein 151*471a92f8SSasha Finkelstein apple_z2_parse_touches(z2, z2->rx_buf + 5, pkt_len - 5); 152*471a92f8SSasha Finkelstein 153*471a92f8SSasha Finkelstein return 0; 154*471a92f8SSasha Finkelstein } 155*471a92f8SSasha Finkelstein 156*471a92f8SSasha Finkelstein static irqreturn_t apple_z2_irq(int irq, void *data) 157*471a92f8SSasha Finkelstein { 158*471a92f8SSasha Finkelstein struct apple_z2 *z2 = data; 159*471a92f8SSasha Finkelstein 160*471a92f8SSasha Finkelstein if (unlikely(!z2->booted)) 161*471a92f8SSasha Finkelstein complete(&z2->boot_irq); 162*471a92f8SSasha Finkelstein else 163*471a92f8SSasha Finkelstein apple_z2_read_packet(z2); 164*471a92f8SSasha Finkelstein 165*471a92f8SSasha Finkelstein return IRQ_HANDLED; 166*471a92f8SSasha Finkelstein } 167*471a92f8SSasha Finkelstein 168*471a92f8SSasha Finkelstein /* Build calibration blob, caller is responsible for freeing the blob data. */ 169*471a92f8SSasha Finkelstein static const u8 *apple_z2_build_cal_blob(struct apple_z2 *z2, 170*471a92f8SSasha Finkelstein u32 address, size_t *size) 171*471a92f8SSasha Finkelstein { 172*471a92f8SSasha Finkelstein u8 *cal_data; 173*471a92f8SSasha Finkelstein int cal_size; 174*471a92f8SSasha Finkelstein size_t blob_size; 175*471a92f8SSasha Finkelstein u32 checksum; 176*471a92f8SSasha Finkelstein u16 checksum_hdr; 177*471a92f8SSasha Finkelstein int i; 178*471a92f8SSasha Finkelstein struct apple_z2_hbpp_blob_hdr *hdr; 179*471a92f8SSasha Finkelstein int error; 180*471a92f8SSasha Finkelstein 181*471a92f8SSasha Finkelstein if (!device_property_present(&z2->spidev->dev, CAL_PROP_NAME)) 182*471a92f8SSasha Finkelstein return NULL; 183*471a92f8SSasha Finkelstein 184*471a92f8SSasha Finkelstein cal_size = device_property_count_u8(&z2->spidev->dev, CAL_PROP_NAME); 185*471a92f8SSasha Finkelstein if (cal_size < 0) 186*471a92f8SSasha Finkelstein return ERR_PTR(cal_size); 187*471a92f8SSasha Finkelstein 188*471a92f8SSasha Finkelstein blob_size = sizeof(struct apple_z2_hbpp_blob_hdr) + cal_size + sizeof(__le32); 189*471a92f8SSasha Finkelstein u8 *blob_data __free(kfree) = kzalloc(blob_size, GFP_KERNEL); 190*471a92f8SSasha Finkelstein if (!blob_data) 191*471a92f8SSasha Finkelstein return ERR_PTR(-ENOMEM); 192*471a92f8SSasha Finkelstein 193*471a92f8SSasha Finkelstein hdr = (struct apple_z2_hbpp_blob_hdr *)blob_data; 194*471a92f8SSasha Finkelstein hdr->cmd = cpu_to_le16(APPLE_Z2_HBPP_CMD_BLOB); 195*471a92f8SSasha Finkelstein hdr->len = cpu_to_le16(round_up(cal_size, 4) / 4); 196*471a92f8SSasha Finkelstein hdr->addr = cpu_to_le32(address); 197*471a92f8SSasha Finkelstein 198*471a92f8SSasha Finkelstein checksum_hdr = 0; 199*471a92f8SSasha Finkelstein for (i = 2; i < 8; i++) 200*471a92f8SSasha Finkelstein checksum_hdr += blob_data[i]; 201*471a92f8SSasha Finkelstein hdr->checksum = cpu_to_le16(checksum_hdr); 202*471a92f8SSasha Finkelstein 203*471a92f8SSasha Finkelstein cal_data = blob_data + sizeof(struct apple_z2_hbpp_blob_hdr); 204*471a92f8SSasha Finkelstein error = device_property_read_u8_array(&z2->spidev->dev, CAL_PROP_NAME, 205*471a92f8SSasha Finkelstein cal_data, cal_size); 206*471a92f8SSasha Finkelstein if (error) 207*471a92f8SSasha Finkelstein return ERR_PTR(error); 208*471a92f8SSasha Finkelstein 209*471a92f8SSasha Finkelstein checksum = 0; 210*471a92f8SSasha Finkelstein for (i = 0; i < cal_size; i++) 211*471a92f8SSasha Finkelstein checksum += cal_data[i]; 212*471a92f8SSasha Finkelstein put_unaligned_le32(checksum, cal_data + cal_size); 213*471a92f8SSasha Finkelstein 214*471a92f8SSasha Finkelstein *size = blob_size; 215*471a92f8SSasha Finkelstein return no_free_ptr(blob_data); 216*471a92f8SSasha Finkelstein } 217*471a92f8SSasha Finkelstein 218*471a92f8SSasha Finkelstein static int apple_z2_send_firmware_blob(struct apple_z2 *z2, const u8 *data, 219*471a92f8SSasha Finkelstein u32 size, bool init) 220*471a92f8SSasha Finkelstein { 221*471a92f8SSasha Finkelstein struct spi_message msg; 222*471a92f8SSasha Finkelstein struct spi_transfer blob_xfer, ack_xfer; 223*471a92f8SSasha Finkelstein int error; 224*471a92f8SSasha Finkelstein 225*471a92f8SSasha Finkelstein z2->tx_buf[0] = 0x1a; 226*471a92f8SSasha Finkelstein z2->tx_buf[1] = 0xa1; 227*471a92f8SSasha Finkelstein 228*471a92f8SSasha Finkelstein spi_message_init(&msg); 229*471a92f8SSasha Finkelstein memset(&blob_xfer, 0, sizeof(blob_xfer)); 230*471a92f8SSasha Finkelstein memset(&ack_xfer, 0, sizeof(ack_xfer)); 231*471a92f8SSasha Finkelstein 232*471a92f8SSasha Finkelstein blob_xfer.tx_buf = data; 233*471a92f8SSasha Finkelstein blob_xfer.len = size; 234*471a92f8SSasha Finkelstein blob_xfer.bits_per_word = init ? 8 : 16; 235*471a92f8SSasha Finkelstein spi_message_add_tail(&blob_xfer, &msg); 236*471a92f8SSasha Finkelstein 237*471a92f8SSasha Finkelstein ack_xfer.tx_buf = z2->tx_buf; 238*471a92f8SSasha Finkelstein ack_xfer.len = 2; 239*471a92f8SSasha Finkelstein spi_message_add_tail(&ack_xfer, &msg); 240*471a92f8SSasha Finkelstein 241*471a92f8SSasha Finkelstein reinit_completion(&z2->boot_irq); 242*471a92f8SSasha Finkelstein error = spi_sync(z2->spidev, &msg); 243*471a92f8SSasha Finkelstein if (error) 244*471a92f8SSasha Finkelstein return error; 245*471a92f8SSasha Finkelstein 246*471a92f8SSasha Finkelstein /* Irq only happens sometimes, but the thing boots reliably nonetheless */ 247*471a92f8SSasha Finkelstein wait_for_completion_timeout(&z2->boot_irq, msecs_to_jiffies(20)); 248*471a92f8SSasha Finkelstein 249*471a92f8SSasha Finkelstein return 0; 250*471a92f8SSasha Finkelstein } 251*471a92f8SSasha Finkelstein 252*471a92f8SSasha Finkelstein static int apple_z2_upload_firmware(struct apple_z2 *z2) 253*471a92f8SSasha Finkelstein { 254*471a92f8SSasha Finkelstein const struct apple_z2_fw_hdr *fw_hdr; 255*471a92f8SSasha Finkelstein size_t fw_idx = sizeof(struct apple_z2_fw_hdr); 256*471a92f8SSasha Finkelstein int error; 257*471a92f8SSasha Finkelstein u32 load_cmd; 258*471a92f8SSasha Finkelstein u32 address; 259*471a92f8SSasha Finkelstein bool init; 260*471a92f8SSasha Finkelstein size_t size; 261*471a92f8SSasha Finkelstein 262*471a92f8SSasha Finkelstein const struct firmware *fw __free(firmware) = NULL; 263*471a92f8SSasha Finkelstein error = request_firmware(&fw, z2->fw_name, &z2->spidev->dev); 264*471a92f8SSasha Finkelstein if (error) { 265*471a92f8SSasha Finkelstein dev_err(&z2->spidev->dev, "unable to load firmware\n"); 266*471a92f8SSasha Finkelstein return error; 267*471a92f8SSasha Finkelstein } 268*471a92f8SSasha Finkelstein 269*471a92f8SSasha Finkelstein fw_hdr = (const struct apple_z2_fw_hdr *)fw->data; 270*471a92f8SSasha Finkelstein if (le32_to_cpu(fw_hdr->magic) != APPLE_Z2_FW_MAGIC || le32_to_cpu(fw_hdr->version) != 1) { 271*471a92f8SSasha Finkelstein dev_err(&z2->spidev->dev, "invalid firmware header\n"); 272*471a92f8SSasha Finkelstein return -EINVAL; 273*471a92f8SSasha Finkelstein } 274*471a92f8SSasha Finkelstein 275*471a92f8SSasha Finkelstein /* 276*471a92f8SSasha Finkelstein * This will interrupt the upload half-way if the file is malformed 277*471a92f8SSasha Finkelstein * As the device has no non-volatile storage to corrupt, and gets reset 278*471a92f8SSasha Finkelstein * on boot anyway, this is fine. 279*471a92f8SSasha Finkelstein */ 280*471a92f8SSasha Finkelstein while (fw_idx < fw->size) { 281*471a92f8SSasha Finkelstein if (fw->size - fw_idx < 8) { 282*471a92f8SSasha Finkelstein dev_err(&z2->spidev->dev, "firmware malformed\n"); 283*471a92f8SSasha Finkelstein return -EINVAL; 284*471a92f8SSasha Finkelstein } 285*471a92f8SSasha Finkelstein 286*471a92f8SSasha Finkelstein load_cmd = le32_to_cpup((__force __le32 *)(fw->data + fw_idx)); 287*471a92f8SSasha Finkelstein fw_idx += sizeof(u32); 288*471a92f8SSasha Finkelstein if (load_cmd == LOAD_COMMAND_INIT_PAYLOAD || load_cmd == LOAD_COMMAND_SEND_BLOB) { 289*471a92f8SSasha Finkelstein size = le32_to_cpup((__force __le32 *)(fw->data + fw_idx)); 290*471a92f8SSasha Finkelstein fw_idx += sizeof(u32); 291*471a92f8SSasha Finkelstein if (fw->size - fw_idx < size) { 292*471a92f8SSasha Finkelstein dev_err(&z2->spidev->dev, "firmware malformed\n"); 293*471a92f8SSasha Finkelstein return -EINVAL; 294*471a92f8SSasha Finkelstein } 295*471a92f8SSasha Finkelstein init = load_cmd == LOAD_COMMAND_INIT_PAYLOAD; 296*471a92f8SSasha Finkelstein error = apple_z2_send_firmware_blob(z2, fw->data + fw_idx, 297*471a92f8SSasha Finkelstein size, init); 298*471a92f8SSasha Finkelstein if (error) 299*471a92f8SSasha Finkelstein return error; 300*471a92f8SSasha Finkelstein fw_idx += size; 301*471a92f8SSasha Finkelstein } else if (load_cmd == LOAD_COMMAND_SEND_CALIBRATION) { 302*471a92f8SSasha Finkelstein address = le32_to_cpup((__force __le32 *)(fw->data + fw_idx)); 303*471a92f8SSasha Finkelstein fw_idx += sizeof(u32); 304*471a92f8SSasha Finkelstein 305*471a92f8SSasha Finkelstein const u8 *data __free(kfree) = 306*471a92f8SSasha Finkelstein apple_z2_build_cal_blob(z2, address, &size); 307*471a92f8SSasha Finkelstein if (IS_ERR(data)) 308*471a92f8SSasha Finkelstein return PTR_ERR(data); 309*471a92f8SSasha Finkelstein 310*471a92f8SSasha Finkelstein if (data) { 311*471a92f8SSasha Finkelstein error = apple_z2_send_firmware_blob(z2, data, size, false); 312*471a92f8SSasha Finkelstein if (error) 313*471a92f8SSasha Finkelstein return error; 314*471a92f8SSasha Finkelstein } 315*471a92f8SSasha Finkelstein } else { 316*471a92f8SSasha Finkelstein dev_err(&z2->spidev->dev, "firmware malformed\n"); 317*471a92f8SSasha Finkelstein return -EINVAL; 318*471a92f8SSasha Finkelstein } 319*471a92f8SSasha Finkelstein fw_idx = round_up(fw_idx, 4); 320*471a92f8SSasha Finkelstein } 321*471a92f8SSasha Finkelstein 322*471a92f8SSasha Finkelstein 323*471a92f8SSasha Finkelstein z2->booted = true; 324*471a92f8SSasha Finkelstein apple_z2_read_packet(z2); 325*471a92f8SSasha Finkelstein return 0; 326*471a92f8SSasha Finkelstein } 327*471a92f8SSasha Finkelstein 328*471a92f8SSasha Finkelstein static int apple_z2_boot(struct apple_z2 *z2) 329*471a92f8SSasha Finkelstein { 330*471a92f8SSasha Finkelstein int error; 331*471a92f8SSasha Finkelstein 332*471a92f8SSasha Finkelstein reinit_completion(&z2->boot_irq); 333*471a92f8SSasha Finkelstein enable_irq(z2->spidev->irq); 334*471a92f8SSasha Finkelstein gpiod_set_value(z2->reset_gpio, 0); 335*471a92f8SSasha Finkelstein if (!wait_for_completion_timeout(&z2->boot_irq, msecs_to_jiffies(20))) 336*471a92f8SSasha Finkelstein return -ETIMEDOUT; 337*471a92f8SSasha Finkelstein 338*471a92f8SSasha Finkelstein error = apple_z2_upload_firmware(z2); 339*471a92f8SSasha Finkelstein if (error) { 340*471a92f8SSasha Finkelstein gpiod_set_value(z2->reset_gpio, 1); 341*471a92f8SSasha Finkelstein disable_irq(z2->spidev->irq); 342*471a92f8SSasha Finkelstein return error; 343*471a92f8SSasha Finkelstein } 344*471a92f8SSasha Finkelstein 345*471a92f8SSasha Finkelstein return 0; 346*471a92f8SSasha Finkelstein } 347*471a92f8SSasha Finkelstein 348*471a92f8SSasha Finkelstein static int apple_z2_probe(struct spi_device *spi) 349*471a92f8SSasha Finkelstein { 350*471a92f8SSasha Finkelstein struct device *dev = &spi->dev; 351*471a92f8SSasha Finkelstein struct apple_z2 *z2; 352*471a92f8SSasha Finkelstein int error; 353*471a92f8SSasha Finkelstein 354*471a92f8SSasha Finkelstein z2 = devm_kzalloc(dev, sizeof(*z2), GFP_KERNEL); 355*471a92f8SSasha Finkelstein if (!z2) 356*471a92f8SSasha Finkelstein return -ENOMEM; 357*471a92f8SSasha Finkelstein 358*471a92f8SSasha Finkelstein z2->tx_buf = devm_kzalloc(dev, sizeof(struct apple_z2_read_interrupt_cmd), GFP_KERNEL); 359*471a92f8SSasha Finkelstein if (!z2->tx_buf) 360*471a92f8SSasha Finkelstein return -ENOMEM; 361*471a92f8SSasha Finkelstein /* 4096 will end up being rounded up to 8192 due to devres header */ 362*471a92f8SSasha Finkelstein z2->rx_buf = devm_kzalloc(dev, 4000, GFP_KERNEL); 363*471a92f8SSasha Finkelstein if (!z2->rx_buf) 364*471a92f8SSasha Finkelstein return -ENOMEM; 365*471a92f8SSasha Finkelstein 366*471a92f8SSasha Finkelstein z2->spidev = spi; 367*471a92f8SSasha Finkelstein init_completion(&z2->boot_irq); 368*471a92f8SSasha Finkelstein spi_set_drvdata(spi, z2); 369*471a92f8SSasha Finkelstein 370*471a92f8SSasha Finkelstein /* Reset the device on boot */ 371*471a92f8SSasha Finkelstein z2->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 372*471a92f8SSasha Finkelstein if (IS_ERR(z2->reset_gpio)) 373*471a92f8SSasha Finkelstein return dev_err_probe(dev, PTR_ERR(z2->reset_gpio), "unable to get reset\n"); 374*471a92f8SSasha Finkelstein 375*471a92f8SSasha Finkelstein error = devm_request_threaded_irq(dev, z2->spidev->irq, NULL, apple_z2_irq, 376*471a92f8SSasha Finkelstein IRQF_ONESHOT | IRQF_NO_AUTOEN, 377*471a92f8SSasha Finkelstein "apple-z2-irq", z2); 378*471a92f8SSasha Finkelstein if (error) 379*471a92f8SSasha Finkelstein return dev_err_probe(dev, error, "unable to request irq\n"); 380*471a92f8SSasha Finkelstein 381*471a92f8SSasha Finkelstein error = device_property_read_string(dev, "firmware-name", &z2->fw_name); 382*471a92f8SSasha Finkelstein if (error) 383*471a92f8SSasha Finkelstein return dev_err_probe(dev, error, "unable to get firmware name\n"); 384*471a92f8SSasha Finkelstein 385*471a92f8SSasha Finkelstein z2->input_dev = devm_input_allocate_device(dev); 386*471a92f8SSasha Finkelstein if (!z2->input_dev) 387*471a92f8SSasha Finkelstein return -ENOMEM; 388*471a92f8SSasha Finkelstein 389*471a92f8SSasha Finkelstein z2->input_dev->name = (char *)spi_get_device_id(spi)->driver_data; 390*471a92f8SSasha Finkelstein z2->input_dev->phys = "apple_z2"; 391*471a92f8SSasha Finkelstein z2->input_dev->id.bustype = BUS_SPI; 392*471a92f8SSasha Finkelstein 393*471a92f8SSasha Finkelstein /* Allocate the axes before setting from DT */ 394*471a92f8SSasha Finkelstein input_set_abs_params(z2->input_dev, ABS_MT_POSITION_X, 0, 0, 0, 0); 395*471a92f8SSasha Finkelstein input_set_abs_params(z2->input_dev, ABS_MT_POSITION_Y, 0, 0, 0, 0); 396*471a92f8SSasha Finkelstein touchscreen_parse_properties(z2->input_dev, true, &z2->props); 397*471a92f8SSasha Finkelstein input_abs_set_res(z2->input_dev, ABS_MT_POSITION_X, 100); 398*471a92f8SSasha Finkelstein input_abs_set_res(z2->input_dev, ABS_MT_POSITION_Y, 100); 399*471a92f8SSasha Finkelstein input_set_abs_params(z2->input_dev, ABS_MT_WIDTH_MAJOR, 0, 65535, 0, 0); 400*471a92f8SSasha Finkelstein input_set_abs_params(z2->input_dev, ABS_MT_WIDTH_MINOR, 0, 65535, 0, 0); 401*471a92f8SSasha Finkelstein input_set_abs_params(z2->input_dev, ABS_MT_TOUCH_MAJOR, 0, 65535, 0, 0); 402*471a92f8SSasha Finkelstein input_set_abs_params(z2->input_dev, ABS_MT_TOUCH_MINOR, 0, 65535, 0, 0); 403*471a92f8SSasha Finkelstein input_set_abs_params(z2->input_dev, ABS_MT_ORIENTATION, -32768, 32767, 0, 0); 404*471a92f8SSasha Finkelstein 405*471a92f8SSasha Finkelstein error = input_mt_init_slots(z2->input_dev, 256, INPUT_MT_DIRECT); 406*471a92f8SSasha Finkelstein if (error) 407*471a92f8SSasha Finkelstein return dev_err_probe(dev, error, "unable to initialize multitouch slots\n"); 408*471a92f8SSasha Finkelstein 409*471a92f8SSasha Finkelstein error = input_register_device(z2->input_dev); 410*471a92f8SSasha Finkelstein if (error) 411*471a92f8SSasha Finkelstein return dev_err_probe(dev, error, "unable to register input device\n"); 412*471a92f8SSasha Finkelstein 413*471a92f8SSasha Finkelstein /* Wait for device reset to finish */ 414*471a92f8SSasha Finkelstein usleep_range(5000, 10000); 415*471a92f8SSasha Finkelstein error = apple_z2_boot(z2); 416*471a92f8SSasha Finkelstein if (error) 417*471a92f8SSasha Finkelstein return error; 418*471a92f8SSasha Finkelstein 419*471a92f8SSasha Finkelstein return 0; 420*471a92f8SSasha Finkelstein } 421*471a92f8SSasha Finkelstein 422*471a92f8SSasha Finkelstein static void apple_z2_shutdown(struct spi_device *spi) 423*471a92f8SSasha Finkelstein { 424*471a92f8SSasha Finkelstein struct apple_z2 *z2 = spi_get_drvdata(spi); 425*471a92f8SSasha Finkelstein 426*471a92f8SSasha Finkelstein disable_irq(z2->spidev->irq); 427*471a92f8SSasha Finkelstein gpiod_direction_output(z2->reset_gpio, 1); 428*471a92f8SSasha Finkelstein z2->booted = false; 429*471a92f8SSasha Finkelstein } 430*471a92f8SSasha Finkelstein 431*471a92f8SSasha Finkelstein static int apple_z2_suspend(struct device *dev) 432*471a92f8SSasha Finkelstein { 433*471a92f8SSasha Finkelstein apple_z2_shutdown(to_spi_device(dev)); 434*471a92f8SSasha Finkelstein 435*471a92f8SSasha Finkelstein return 0; 436*471a92f8SSasha Finkelstein } 437*471a92f8SSasha Finkelstein 438*471a92f8SSasha Finkelstein static int apple_z2_resume(struct device *dev) 439*471a92f8SSasha Finkelstein { 440*471a92f8SSasha Finkelstein struct apple_z2 *z2 = spi_get_drvdata(to_spi_device(dev)); 441*471a92f8SSasha Finkelstein 442*471a92f8SSasha Finkelstein return apple_z2_boot(z2); 443*471a92f8SSasha Finkelstein } 444*471a92f8SSasha Finkelstein 445*471a92f8SSasha Finkelstein static DEFINE_SIMPLE_DEV_PM_OPS(apple_z2_pm, apple_z2_suspend, apple_z2_resume); 446*471a92f8SSasha Finkelstein 447*471a92f8SSasha Finkelstein static const struct of_device_id apple_z2_of_match[] = { 448*471a92f8SSasha Finkelstein { .compatible = "apple,j293-touchbar" }, 449*471a92f8SSasha Finkelstein { .compatible = "apple,j493-touchbar" }, 450*471a92f8SSasha Finkelstein {} 451*471a92f8SSasha Finkelstein }; 452*471a92f8SSasha Finkelstein MODULE_DEVICE_TABLE(of, apple_z2_of_match); 453*471a92f8SSasha Finkelstein 454*471a92f8SSasha Finkelstein static struct spi_device_id apple_z2_of_id[] = { 455*471a92f8SSasha Finkelstein { .name = "j293-touchbar", .driver_data = (kernel_ulong_t)"MacBookPro17,1 Touch Bar" }, 456*471a92f8SSasha Finkelstein { .name = "j493-touchbar", .driver_data = (kernel_ulong_t)"Mac14,7 Touch Bar" }, 457*471a92f8SSasha Finkelstein {} 458*471a92f8SSasha Finkelstein }; 459*471a92f8SSasha Finkelstein MODULE_DEVICE_TABLE(spi, apple_z2_of_id); 460*471a92f8SSasha Finkelstein 461*471a92f8SSasha Finkelstein static struct spi_driver apple_z2_driver = { 462*471a92f8SSasha Finkelstein .driver = { 463*471a92f8SSasha Finkelstein .name = "apple-z2", 464*471a92f8SSasha Finkelstein .pm = pm_sleep_ptr(&apple_z2_pm), 465*471a92f8SSasha Finkelstein .of_match_table = apple_z2_of_match, 466*471a92f8SSasha Finkelstein .probe_type = PROBE_PREFER_ASYNCHRONOUS, 467*471a92f8SSasha Finkelstein }, 468*471a92f8SSasha Finkelstein .id_table = apple_z2_of_id, 469*471a92f8SSasha Finkelstein .probe = apple_z2_probe, 470*471a92f8SSasha Finkelstein .remove = apple_z2_shutdown, 471*471a92f8SSasha Finkelstein }; 472*471a92f8SSasha Finkelstein 473*471a92f8SSasha Finkelstein module_spi_driver(apple_z2_driver); 474*471a92f8SSasha Finkelstein 475*471a92f8SSasha Finkelstein MODULE_LICENSE("GPL"); 476*471a92f8SSasha Finkelstein MODULE_FIRMWARE("apple/dfrmtfw-*.bin"); 477*471a92f8SSasha Finkelstein MODULE_DESCRIPTION("Apple Z2 touchscreens driver"); 478