Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only 2 : : /* 3 : : * ST Microelectronics MFD: stmpe's spi client specific driver 4 : : * 5 : : * Copyright (C) ST Microelectronics SA 2011 6 : : * 7 : : * Author: Viresh Kumar <vireshk@kernel.org> for ST Microelectronics 8 : : */ 9 : : 10 : : #include <linux/spi/spi.h> 11 : : #include <linux/interrupt.h> 12 : : #include <linux/kernel.h> 13 : : #include <linux/module.h> 14 : : #include <linux/of.h> 15 : : #include <linux/types.h> 16 : : #include "stmpe.h" 17 : : 18 : : #define READ_CMD (1 << 7) 19 : : 20 : 0 : static int spi_reg_read(struct stmpe *stmpe, u8 reg) 21 : : { 22 : 0 : struct spi_device *spi = stmpe->client; 23 : 0 : int status = spi_w8r16(spi, reg | READ_CMD); 24 : : 25 : 0 : return (status < 0) ? status : status >> 8; 26 : : } 27 : : 28 : 0 : static int spi_reg_write(struct stmpe *stmpe, u8 reg, u8 val) 29 : : { 30 : 0 : struct spi_device *spi = stmpe->client; 31 : 0 : u16 cmd = (val << 8) | reg; 32 : : 33 : 0 : return spi_write(spi, (const u8 *)&cmd, 2); 34 : : } 35 : : 36 : 0 : static int spi_block_read(struct stmpe *stmpe, u8 reg, u8 length, u8 *values) 37 : : { 38 : : int ret, i; 39 : : 40 : 0 : for (i = 0; i < length; i++) { 41 : 0 : ret = spi_reg_read(stmpe, reg + i); 42 : 0 : if (ret < 0) 43 : 0 : return ret; 44 : 0 : *(values + i) = ret; 45 : : } 46 : : 47 : : return 0; 48 : : } 49 : : 50 : 0 : static int spi_block_write(struct stmpe *stmpe, u8 reg, u8 length, 51 : : const u8 *values) 52 : : { 53 : : int ret = 0, i; 54 : : 55 : 0 : for (i = length; i > 0; i--, reg++) { 56 : 0 : ret = spi_reg_write(stmpe, reg, *(values + i - 1)); 57 : 0 : if (ret < 0) 58 : 0 : return ret; 59 : : } 60 : : 61 : 0 : return ret; 62 : : } 63 : : 64 : 0 : static void spi_init(struct stmpe *stmpe) 65 : : { 66 : 0 : struct spi_device *spi = stmpe->client; 67 : : 68 : 0 : spi->bits_per_word = 8; 69 : : 70 : : /* This register is only present for stmpe811 */ 71 : 0 : if (stmpe->variant->id_val == 0x0811) 72 : 0 : spi_reg_write(stmpe, STMPE811_REG_SPI_CFG, spi->mode); 73 : : 74 : 0 : if (spi_setup(spi) < 0) 75 : : dev_dbg(&spi->dev, "spi_setup failed\n"); 76 : 0 : } 77 : : 78 : : static struct stmpe_client_info spi_ci = { 79 : : .read_byte = spi_reg_read, 80 : : .write_byte = spi_reg_write, 81 : : .read_block = spi_block_read, 82 : : .write_block = spi_block_write, 83 : : .init = spi_init, 84 : : }; 85 : : 86 : : static int 87 : 0 : stmpe_spi_probe(struct spi_device *spi) 88 : : { 89 : 0 : const struct spi_device_id *id = spi_get_device_id(spi); 90 : : 91 : : /* don't exceed max specified rate - 1MHz - Limitation of STMPE */ 92 : 0 : if (spi->max_speed_hz > 1000000) { 93 : : dev_dbg(&spi->dev, "f(sample) %d KHz?\n", 94 : : (spi->max_speed_hz/1000)); 95 : : return -EINVAL; 96 : : } 97 : : 98 : 0 : spi_ci.irq = spi->irq; 99 : 0 : spi_ci.client = spi; 100 : 0 : spi_ci.dev = &spi->dev; 101 : : 102 : 0 : return stmpe_probe(&spi_ci, id->driver_data); 103 : : } 104 : : 105 : 0 : static int stmpe_spi_remove(struct spi_device *spi) 106 : : { 107 : : struct stmpe *stmpe = spi_get_drvdata(spi); 108 : : 109 : 0 : return stmpe_remove(stmpe); 110 : : } 111 : : 112 : : static const struct of_device_id stmpe_spi_of_match[] = { 113 : : { .compatible = "st,stmpe610", }, 114 : : { .compatible = "st,stmpe801", }, 115 : : { .compatible = "st,stmpe811", }, 116 : : { .compatible = "st,stmpe1601", }, 117 : : { .compatible = "st,stmpe2401", }, 118 : : { .compatible = "st,stmpe2403", }, 119 : : { /* sentinel */ }, 120 : : }; 121 : : MODULE_DEVICE_TABLE(of, stmpe_spi_of_match); 122 : : 123 : : static const struct spi_device_id stmpe_spi_id[] = { 124 : : { "stmpe610", STMPE610 }, 125 : : { "stmpe801", STMPE801 }, 126 : : { "stmpe811", STMPE811 }, 127 : : { "stmpe1601", STMPE1601 }, 128 : : { "stmpe2401", STMPE2401 }, 129 : : { "stmpe2403", STMPE2403 }, 130 : : { } 131 : : }; 132 : : MODULE_DEVICE_TABLE(spi, stmpe_id); 133 : : 134 : : static struct spi_driver stmpe_spi_driver = { 135 : : .driver = { 136 : : .name = "stmpe-spi", 137 : : .of_match_table = of_match_ptr(stmpe_spi_of_match), 138 : : #ifdef CONFIG_PM 139 : : .pm = &stmpe_dev_pm_ops, 140 : : #endif 141 : : }, 142 : : .probe = stmpe_spi_probe, 143 : : .remove = stmpe_spi_remove, 144 : : .id_table = stmpe_spi_id, 145 : : }; 146 : : 147 : 3 : static int __init stmpe_init(void) 148 : : { 149 : 3 : return spi_register_driver(&stmpe_spi_driver); 150 : : } 151 : : subsys_initcall(stmpe_init); 152 : : 153 : 0 : static void __exit stmpe_exit(void) 154 : : { 155 : : spi_unregister_driver(&stmpe_spi_driver); 156 : 0 : } 157 : : module_exit(stmpe_exit); 158 : : 159 : : MODULE_LICENSE("GPL v2"); 160 : : MODULE_DESCRIPTION("STMPE MFD SPI Interface Driver"); 161 : : MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>");