Merge tag 'sunxi-drm-fixes-for-4.7' of https://git.kernel.org/pub/scm/linux/kernel...
[deliverable/linux.git] / drivers / gpu / drm / nouveau / nvkm / subdev / iccsense / base.c
index 03eef9d2872ce9a12f4f42f2eb2abc1990ad63ee..41bd5d0f76927e1e2f38ffe7e1d3c228a4d05139 100644 (file)
@@ -95,6 +95,63 @@ nvkm_iccsense_ina3221_read(struct nvkm_iccsense *iccsense,
                                       40 * 8);
 }
 
+static void
+nvkm_iccsense_ina209_config(struct nvkm_iccsense *iccsense,
+                           struct nvkm_iccsense_sensor *sensor)
+{
+       struct nvkm_subdev *subdev = &iccsense->subdev;
+       /* configuration:
+        * 0x0007: 0x0007 shunt and bus continous
+        * 0x0078: 0x0078 128 samples shunt
+        * 0x0780: 0x0780 128 samples bus
+        * 0x1800: 0x0000 +-40 mV shunt range
+        * 0x2000: 0x0000 16V FSR
+         */
+       u16 value = 0x07ff;
+       nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value);
+       nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value);
+}
+
+static void
+nvkm_iccsense_ina3221_config(struct nvkm_iccsense *iccsense,
+                            struct nvkm_iccsense_sensor *sensor)
+{
+       struct nvkm_subdev *subdev = &iccsense->subdev;
+       /* configuration:
+        * 0x0007: 0x0007 shunt and bus continous
+        * 0x0031: 0x0000 140 us conversion time shunt
+        * 0x01c0: 0x0000 140 us conversion time bus
+        * 0x0f00: 0x0f00 1024 samples
+        * 0x7000: 0x?000 channels
+         */
+       u16 value = 0x0e07;
+       if (sensor->rail_mask & 0x1)
+               value |= 0x1 << 14;
+       if (sensor->rail_mask & 0x2)
+               value |= 0x1 << 13;
+       if (sensor->rail_mask & 0x4)
+               value |= 0x1 << 12;
+       nvkm_debug(subdev, "config for sensor id %i: 0x%x\n", sensor->id, value);
+       nv_wr16i2cr(sensor->i2c, sensor->addr, 0x00, value);
+}
+
+static void
+nvkm_iccsense_sensor_config(struct nvkm_iccsense *iccsense,
+                           struct nvkm_iccsense_sensor *sensor)
+{
+       switch (sensor->type) {
+       case NVBIOS_EXTDEV_INA209:
+       case NVBIOS_EXTDEV_INA219:
+               nvkm_iccsense_ina209_config(iccsense, sensor);
+               break;
+       case NVBIOS_EXTDEV_INA3221:
+               nvkm_iccsense_ina3221_config(iccsense, sensor);
+               break;
+       default:
+               break;
+       }
+}
+
 int
 nvkm_iccsense_read_all(struct nvkm_iccsense *iccsense)
 {
@@ -219,6 +276,8 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev)
                struct pwr_rail_t *r = &stbl.rail[i];
                struct nvkm_iccsense_rail *rail;
                struct nvkm_iccsense_sensor *sensor;
+               int (*read)(struct nvkm_iccsense *,
+                           struct nvkm_iccsense_rail *);
 
                if (!r->mode || r->resistor_mohm == 0)
                        continue;
@@ -227,31 +286,31 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev)
                if (!sensor)
                        continue;
 
-               rail = kmalloc(sizeof(*rail), GFP_KERNEL);
-               if (!rail)
-                       return -ENOMEM;
-
                switch (sensor->type) {
                case NVBIOS_EXTDEV_INA209:
                        if (r->rail != 0)
                                continue;
-                       rail->read = nvkm_iccsense_ina209_read;
+                       read = nvkm_iccsense_ina209_read;
                        break;
                case NVBIOS_EXTDEV_INA219:
                        if (r->rail != 0)
                                continue;
-                       rail->read = nvkm_iccsense_ina219_read;
+                       read = nvkm_iccsense_ina219_read;
                        break;
                case NVBIOS_EXTDEV_INA3221:
                        if (r->rail >= 3)
                                continue;
-                       rail->read = nvkm_iccsense_ina3221_read;
+                       read = nvkm_iccsense_ina3221_read;
                        break;
                default:
                        continue;
                }
 
+               rail = kmalloc(sizeof(*rail), GFP_KERNEL);
+               if (!rail)
+                       return -ENOMEM;
                sensor->rail_mask |= 1 << r->rail;
+               rail->read = read;
                rail->sensor = sensor;
                rail->idx = r->rail;
                rail->mohm = r->resistor_mohm;
@@ -260,8 +319,19 @@ nvkm_iccsense_oneinit(struct nvkm_subdev *subdev)
        return 0;
 }
 
+static int
+nvkm_iccsense_init(struct nvkm_subdev *subdev)
+{
+       struct nvkm_iccsense *iccsense = nvkm_iccsense(subdev);
+       struct nvkm_iccsense_sensor *sensor;
+       list_for_each_entry(sensor, &iccsense->sensors, head)
+               nvkm_iccsense_sensor_config(iccsense, sensor);
+       return 0;
+}
+
 struct nvkm_subdev_func iccsense_func = {
        .oneinit = nvkm_iccsense_oneinit,
+       .init = nvkm_iccsense_init,
        .dtor = nvkm_iccsense_dtor,
 };
 
@@ -269,7 +339,7 @@ void
 nvkm_iccsense_ctor(struct nvkm_device *device, int index,
                   struct nvkm_iccsense *iccsense)
 {
-       nvkm_subdev_ctor(&iccsense_func, device, index, 0, &iccsense->subdev);
+       nvkm_subdev_ctor(&iccsense_func, device, index, &iccsense->subdev);
 }
 
 int
This page took 0.040598 seconds and 5 git commands to generate.