Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2015 Red Hat Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: Ben Skeggs <bskeggs@redhat.com>
0023  */
0024 #include "pad.h"
0025 
0026 static void
0027 nvkm_i2c_pad_mode_locked(struct nvkm_i2c_pad *pad, enum nvkm_i2c_pad_mode mode)
0028 {
0029     PAD_TRACE(pad, "-> %s", (mode == NVKM_I2C_PAD_AUX) ? "aux" :
0030                   (mode == NVKM_I2C_PAD_I2C) ? "i2c" : "off");
0031     if (pad->func->mode)
0032         pad->func->mode(pad, mode);
0033 }
0034 
0035 void
0036 nvkm_i2c_pad_mode(struct nvkm_i2c_pad *pad, enum nvkm_i2c_pad_mode mode)
0037 {
0038     PAD_TRACE(pad, "mode %d", mode);
0039     mutex_lock(&pad->mutex);
0040     nvkm_i2c_pad_mode_locked(pad, mode);
0041     pad->mode = mode;
0042     mutex_unlock(&pad->mutex);
0043 }
0044 
0045 void
0046 nvkm_i2c_pad_release(struct nvkm_i2c_pad *pad)
0047 {
0048     PAD_TRACE(pad, "release");
0049     if (pad->mode == NVKM_I2C_PAD_OFF)
0050         nvkm_i2c_pad_mode_locked(pad, pad->mode);
0051     mutex_unlock(&pad->mutex);
0052 }
0053 
0054 int
0055 nvkm_i2c_pad_acquire(struct nvkm_i2c_pad *pad, enum nvkm_i2c_pad_mode mode)
0056 {
0057     PAD_TRACE(pad, "acquire");
0058     mutex_lock(&pad->mutex);
0059     if (pad->mode != mode) {
0060         if (pad->mode != NVKM_I2C_PAD_OFF) {
0061             mutex_unlock(&pad->mutex);
0062             return -EBUSY;
0063         }
0064         nvkm_i2c_pad_mode_locked(pad, mode);
0065     }
0066     return 0;
0067 }
0068 
0069 void
0070 nvkm_i2c_pad_fini(struct nvkm_i2c_pad *pad)
0071 {
0072     PAD_TRACE(pad, "fini");
0073     nvkm_i2c_pad_mode_locked(pad, NVKM_I2C_PAD_OFF);
0074 }
0075 
0076 void
0077 nvkm_i2c_pad_init(struct nvkm_i2c_pad *pad)
0078 {
0079     PAD_TRACE(pad, "init");
0080     nvkm_i2c_pad_mode_locked(pad, pad->mode);
0081 }
0082 
0083 void
0084 nvkm_i2c_pad_del(struct nvkm_i2c_pad **ppad)
0085 {
0086     struct nvkm_i2c_pad *pad = *ppad;
0087     if (pad) {
0088         PAD_TRACE(pad, "dtor");
0089         list_del(&pad->head);
0090         kfree(pad);
0091         pad = NULL;
0092     }
0093 }
0094 
0095 void
0096 nvkm_i2c_pad_ctor(const struct nvkm_i2c_pad_func *func, struct nvkm_i2c *i2c,
0097           int id, struct nvkm_i2c_pad *pad)
0098 {
0099     pad->func = func;
0100     pad->i2c = i2c;
0101     pad->id = id;
0102     pad->mode = NVKM_I2C_PAD_OFF;
0103     mutex_init(&pad->mutex);
0104     list_add_tail(&pad->head, &i2c->pad);
0105     PAD_TRACE(pad, "ctor");
0106 }
0107 
0108 int
0109 nvkm_i2c_pad_new_(const struct nvkm_i2c_pad_func *func, struct nvkm_i2c *i2c,
0110           int id, struct nvkm_i2c_pad **ppad)
0111 {
0112     if (!(*ppad = kzalloc(sizeof(**ppad), GFP_KERNEL)))
0113         return -ENOMEM;
0114     nvkm_i2c_pad_ctor(func, i2c, id, *ppad);
0115     return 0;
0116 }