Home | History | Annotate | Line # | Download | only in gpio
      1 /*	$NetBSD: nouveau_nvkm_subdev_gpio_nv10.c,v 1.3 2021/12/18 23:45:39 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 2009 Francisco Jerez.
      5  * All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining
      8  * a copy of this software and associated documentation files (the
      9  * "Software"), to deal in the Software without restriction, including
     10  * without limitation the rights to use, copy, modify, merge, publish,
     11  * distribute, sublicense, and/or sell copies of the Software, and to
     12  * permit persons to whom the Software is furnished to do so, subject to
     13  * the following conditions:
     14  *
     15  * The above copyright notice and this permission notice (including the
     16  * next paragraph) shall be included in all copies or substantial
     17  * portions of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     20  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     22  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
     23  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     24  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     25  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     26  *
     27  */
     28 #include <sys/cdefs.h>
     29 __KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_subdev_gpio_nv10.c,v 1.3 2021/12/18 23:45:39 riastradh Exp $");
     30 
     31 #include "priv.h"
     32 
     33 static int
     34 nv10_gpio_sense(struct nvkm_gpio *gpio, int line)
     35 {
     36 	struct nvkm_device *device = gpio->subdev.device;
     37 	if (line < 2) {
     38 		line = line * 16;
     39 		line = nvkm_rd32(device, 0x600818) >> line;
     40 		return !!(line & 0x0100);
     41 	} else
     42 	if (line < 10) {
     43 		line = (line - 2) * 4;
     44 		line = nvkm_rd32(device, 0x60081c) >> line;
     45 		return !!(line & 0x04);
     46 	} else
     47 	if (line < 14) {
     48 		line = (line - 10) * 4;
     49 		line = nvkm_rd32(device, 0x600850) >> line;
     50 		return !!(line & 0x04);
     51 	}
     52 
     53 	return -EINVAL;
     54 }
     55 
     56 static int
     57 nv10_gpio_drive(struct nvkm_gpio *gpio, int line, int dir, int out)
     58 {
     59 	struct nvkm_device *device = gpio->subdev.device;
     60 	u32 reg, mask, data;
     61 
     62 	if (line < 2) {
     63 		line = line * 16;
     64 		reg  = 0x600818;
     65 		mask = 0x00000011;
     66 		data = (dir << 4) | out;
     67 	} else
     68 	if (line < 10) {
     69 		line = (line - 2) * 4;
     70 		reg  = 0x60081c;
     71 		mask = 0x00000003;
     72 		data = (dir << 1) | out;
     73 	} else
     74 	if (line < 14) {
     75 		line = (line - 10) * 4;
     76 		reg  = 0x600850;
     77 		mask = 0x00000003;
     78 		data = (dir << 1) | out;
     79 	} else {
     80 		return -EINVAL;
     81 	}
     82 
     83 	nvkm_mask(device, reg, mask << line, data << line);
     84 	return 0;
     85 }
     86 
     87 static void
     88 nv10_gpio_intr_stat(struct nvkm_gpio *gpio, u32 *hi, u32 *lo)
     89 {
     90 	struct nvkm_device *device = gpio->subdev.device;
     91 	u32 intr = nvkm_rd32(device, 0x001104);
     92 	u32 stat = nvkm_rd32(device, 0x001144) & intr;
     93 	*lo = (stat & 0xffff0000) >> 16;
     94 	*hi = (stat & 0x0000ffff);
     95 	nvkm_wr32(device, 0x001104, intr);
     96 }
     97 
     98 static void
     99 nv10_gpio_intr_mask(struct nvkm_gpio *gpio, u32 type, u32 mask, u32 data)
    100 {
    101 	struct nvkm_device *device = gpio->subdev.device;
    102 	u32 inte = nvkm_rd32(device, 0x001144);
    103 	if (type & NVKM_GPIO_LO)
    104 		inte = (inte & ~(mask << 16)) | (data << 16);
    105 	if (type & NVKM_GPIO_HI)
    106 		inte = (inte & ~mask) | data;
    107 	nvkm_wr32(device, 0x001144, inte);
    108 }
    109 
    110 static const struct nvkm_gpio_func
    111 nv10_gpio = {
    112 	.lines = 16,
    113 	.intr_stat = nv10_gpio_intr_stat,
    114 	.intr_mask = nv10_gpio_intr_mask,
    115 	.drive = nv10_gpio_drive,
    116 	.sense = nv10_gpio_sense,
    117 };
    118 
    119 int
    120 nv10_gpio_new(struct nvkm_device *device, int index, struct nvkm_gpio **pgpio)
    121 {
    122 	return nvkm_gpio_new_(&nv10_gpio, device, index, pgpio);
    123 }
    124