Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.15-rc4 133 lines 3.4 kB view raw
1/* 2 * cros_ec_lpc_reg - LPC access to the Chrome OS Embedded Controller 3 * 4 * Copyright (C) 2016 Google, Inc 5 * 6 * This software is licensed under the terms of the GNU General Public 7 * License version 2, as published by the Free Software Foundation, and 8 * may be copied, distributed, and modified under those terms. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * This driver uses the Chrome OS EC byte-level message-based protocol for 16 * communicating the keyboard state (which keys are pressed) from a keyboard EC 17 * to the AP over some bus (such as i2c, lpc, spi). The EC does debouncing, 18 * but everything else (including deghosting) is done here. The main 19 * motivation for this is to keep the EC firmware as simple as possible, since 20 * it cannot be easily upgraded and EC flash/IRAM space is relatively 21 * expensive. 22 */ 23 24#include <linux/io.h> 25#include <linux/mfd/cros_ec.h> 26#include <linux/mfd/cros_ec_commands.h> 27#include <linux/mfd/cros_ec_lpc_mec.h> 28 29static u8 lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest) 30{ 31 int i; 32 int sum = 0; 33 34 for (i = 0; i < length; ++i) { 35 dest[i] = inb(offset + i); 36 sum += dest[i]; 37 } 38 39 /* Return checksum of all bytes read */ 40 return sum; 41} 42 43static u8 lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg) 44{ 45 int i; 46 int sum = 0; 47 48 for (i = 0; i < length; ++i) { 49 outb(msg[i], offset + i); 50 sum += msg[i]; 51 } 52 53 /* Return checksum of all bytes written */ 54 return sum; 55} 56 57#ifdef CONFIG_CROS_EC_LPC_MEC 58 59u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest) 60{ 61 if (length == 0) 62 return 0; 63 64 /* Access desired range through EMI interface */ 65 if (offset >= MEC_EMI_RANGE_START && offset <= MEC_EMI_RANGE_END) { 66 /* Ensure we don't straddle EMI region */ 67 if (WARN_ON(offset + length - 1 > MEC_EMI_RANGE_END)) 68 return 0; 69 70 return cros_ec_lpc_io_bytes_mec(MEC_IO_READ, offset, length, 71 dest); 72 } 73 74 if (WARN_ON(offset + length > MEC_EMI_RANGE_START && 75 offset < MEC_EMI_RANGE_START)) 76 return 0; 77 78 return lpc_read_bytes(offset, length, dest); 79} 80 81u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg) 82{ 83 if (length == 0) 84 return 0; 85 86 /* Access desired range through EMI interface */ 87 if (offset >= MEC_EMI_RANGE_START && offset <= MEC_EMI_RANGE_END) { 88 /* Ensure we don't straddle EMI region */ 89 if (WARN_ON(offset + length - 1 > MEC_EMI_RANGE_END)) 90 return 0; 91 92 return cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, offset, length, 93 msg); 94 } 95 96 if (WARN_ON(offset + length > MEC_EMI_RANGE_START && 97 offset < MEC_EMI_RANGE_START)) 98 return 0; 99 100 return lpc_write_bytes(offset, length, msg); 101} 102 103void cros_ec_lpc_reg_init(void) 104{ 105 cros_ec_lpc_mec_init(); 106} 107 108void cros_ec_lpc_reg_destroy(void) 109{ 110 cros_ec_lpc_mec_destroy(); 111} 112 113#else /* CONFIG_CROS_EC_LPC_MEC */ 114 115u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest) 116{ 117 return lpc_read_bytes(offset, length, dest); 118} 119 120u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg) 121{ 122 return lpc_write_bytes(offset, length, msg); 123} 124 125void cros_ec_lpc_reg_init(void) 126{ 127} 128 129void cros_ec_lpc_reg_destroy(void) 130{ 131} 132 133#endif /* CONFIG_CROS_EC_LPC_MEC */