0001
0002
0003
0004
0005
0006 #include <linux/delay.h>
0007 #include <linux/io.h>
0008 #include <linux/mutex.h>
0009 #include <linux/types.h>
0010
0011 #include "cros_ec_lpc_mec.h"
0012
0013
0014
0015
0016
0017 static DEFINE_MUTEX(io_mutex);
0018 static u16 mec_emi_base, mec_emi_end;
0019
0020
0021
0022
0023
0024
0025
0026 static void cros_ec_lpc_mec_emi_write_address(u16 addr,
0027 enum cros_ec_lpc_mec_emi_access_mode access_type)
0028 {
0029 outb((addr & 0xfc) | access_type, MEC_EMI_EC_ADDRESS_B0(mec_emi_base));
0030 outb((addr >> 8) & 0x7f, MEC_EMI_EC_ADDRESS_B1(mec_emi_base));
0031 }
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 int cros_ec_lpc_mec_in_range(unsigned int offset, unsigned int length)
0043 {
0044 if (length == 0)
0045 return -EINVAL;
0046
0047 if (WARN_ON(mec_emi_base == 0 || mec_emi_end == 0))
0048 return -EINVAL;
0049
0050 if (offset >= mec_emi_base && offset < mec_emi_end) {
0051 if (WARN_ON(offset + length - 1 >= mec_emi_end))
0052 return -EINVAL;
0053 return 1;
0054 }
0055
0056 if (WARN_ON(offset + length > mec_emi_base && offset < mec_emi_end))
0057 return -EINVAL;
0058
0059 return 0;
0060 }
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type,
0073 unsigned int offset, unsigned int length,
0074 u8 *buf)
0075 {
0076 int i = 0;
0077 int io_addr;
0078 u8 sum = 0;
0079 enum cros_ec_lpc_mec_emi_access_mode access, new_access;
0080
0081
0082 WARN_ON(mec_emi_base == 0 || mec_emi_end == 0);
0083 if (mec_emi_base == 0 || mec_emi_end == 0)
0084 return 0;
0085
0086
0087
0088
0089
0090 if (offset & 0x3 || length < 4)
0091 access = ACCESS_TYPE_BYTE;
0092 else
0093 access = ACCESS_TYPE_LONG_AUTO_INCREMENT;
0094
0095 mutex_lock(&io_mutex);
0096
0097
0098 cros_ec_lpc_mec_emi_write_address(offset, access);
0099
0100
0101 io_addr = MEC_EMI_EC_DATA_B0(mec_emi_base) + (offset & 0x3);
0102 while (i < length) {
0103 while (io_addr <= MEC_EMI_EC_DATA_B3(mec_emi_base)) {
0104 if (io_type == MEC_IO_READ)
0105 buf[i] = inb(io_addr++);
0106 else
0107 outb(buf[i], io_addr++);
0108
0109 sum += buf[i++];
0110 offset++;
0111
0112
0113 if (i == length)
0114 goto done;
0115 }
0116
0117
0118
0119
0120
0121 if (length - i < 4 && io_type == MEC_IO_WRITE)
0122 new_access = ACCESS_TYPE_BYTE;
0123 else
0124 new_access = ACCESS_TYPE_LONG_AUTO_INCREMENT;
0125
0126 if (new_access != access ||
0127 access != ACCESS_TYPE_LONG_AUTO_INCREMENT) {
0128 access = new_access;
0129 cros_ec_lpc_mec_emi_write_address(offset, access);
0130 }
0131
0132
0133 io_addr = MEC_EMI_EC_DATA_B0(mec_emi_base);
0134 }
0135
0136 done:
0137 mutex_unlock(&io_mutex);
0138
0139 return sum;
0140 }
0141 EXPORT_SYMBOL(cros_ec_lpc_io_bytes_mec);
0142
0143 void cros_ec_lpc_mec_init(unsigned int base, unsigned int end)
0144 {
0145 mec_emi_base = base;
0146 mec_emi_end = end;
0147 }
0148 EXPORT_SYMBOL(cros_ec_lpc_mec_init);
0149
0150 void cros_ec_lpc_mec_destroy(void)
0151 {
0152 mutex_destroy(&io_mutex);
0153 }
0154 EXPORT_SYMBOL(cros_ec_lpc_mec_destroy);