0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "priv.h"
0027
0028 static int
0029 nv10_gpio_sense(struct nvkm_gpio *gpio, int line)
0030 {
0031 struct nvkm_device *device = gpio->subdev.device;
0032 if (line < 2) {
0033 line = line * 16;
0034 line = nvkm_rd32(device, 0x600818) >> line;
0035 return !!(line & 0x0100);
0036 } else
0037 if (line < 10) {
0038 line = (line - 2) * 4;
0039 line = nvkm_rd32(device, 0x60081c) >> line;
0040 return !!(line & 0x04);
0041 } else
0042 if (line < 14) {
0043 line = (line - 10) * 4;
0044 line = nvkm_rd32(device, 0x600850) >> line;
0045 return !!(line & 0x04);
0046 }
0047
0048 return -EINVAL;
0049 }
0050
0051 static int
0052 nv10_gpio_drive(struct nvkm_gpio *gpio, int line, int dir, int out)
0053 {
0054 struct nvkm_device *device = gpio->subdev.device;
0055 u32 reg, mask, data;
0056
0057 if (line < 2) {
0058 line = line * 16;
0059 reg = 0x600818;
0060 mask = 0x00000011;
0061 data = (dir << 4) | out;
0062 } else
0063 if (line < 10) {
0064 line = (line - 2) * 4;
0065 reg = 0x60081c;
0066 mask = 0x00000003;
0067 data = (dir << 1) | out;
0068 } else
0069 if (line < 14) {
0070 line = (line - 10) * 4;
0071 reg = 0x600850;
0072 mask = 0x00000003;
0073 data = (dir << 1) | out;
0074 } else {
0075 return -EINVAL;
0076 }
0077
0078 nvkm_mask(device, reg, mask << line, data << line);
0079 return 0;
0080 }
0081
0082 static void
0083 nv10_gpio_intr_stat(struct nvkm_gpio *gpio, u32 *hi, u32 *lo)
0084 {
0085 struct nvkm_device *device = gpio->subdev.device;
0086 u32 intr = nvkm_rd32(device, 0x001104);
0087 u32 stat = nvkm_rd32(device, 0x001144) & intr;
0088 *lo = (stat & 0xffff0000) >> 16;
0089 *hi = (stat & 0x0000ffff);
0090 nvkm_wr32(device, 0x001104, intr);
0091 }
0092
0093 static void
0094 nv10_gpio_intr_mask(struct nvkm_gpio *gpio, u32 type, u32 mask, u32 data)
0095 {
0096 struct nvkm_device *device = gpio->subdev.device;
0097 u32 inte = nvkm_rd32(device, 0x001144);
0098 if (type & NVKM_GPIO_LO)
0099 inte = (inte & ~(mask << 16)) | (data << 16);
0100 if (type & NVKM_GPIO_HI)
0101 inte = (inte & ~mask) | data;
0102 nvkm_wr32(device, 0x001144, inte);
0103 }
0104
0105 static const struct nvkm_gpio_func
0106 nv10_gpio = {
0107 .lines = 16,
0108 .intr_stat = nv10_gpio_intr_stat,
0109 .intr_mask = nv10_gpio_intr_mask,
0110 .drive = nv10_gpio_drive,
0111 .sense = nv10_gpio_sense,
0112 };
0113
0114 int
0115 nv10_gpio_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
0116 struct nvkm_gpio **pgpio)
0117 {
0118 return nvkm_gpio_new_(&nv10_gpio, device, type, inst, pgpio);
0119 }