/* 
 | 
 * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw> 
 | 
 * 
 | 
 * SPDX-License-Identifier:    GPL-2.0+ 
 | 
 */ 
 | 
  
 | 
#include <common.h> 
 | 
#include <dm.h> 
 | 
#include <errno.h> 
 | 
#include <misc.h> 
 | 
  
 | 
/* 
 | 
 * Implement a  miscellaneous uclass for those do not fit other more 
 | 
 * general classes. A set of generic read, write and ioctl methods may 
 | 
 * be used to access the device. 
 | 
 */ 
 | 
  
 | 
int misc_read(struct udevice *dev, int offset, void *buf, int size) 
 | 
{ 
 | 
    const struct misc_ops *ops = device_get_ops(dev); 
 | 
  
 | 
    if (!ops->read) 
 | 
        return -ENOSYS; 
 | 
  
 | 
    return ops->read(dev, offset, buf, size); 
 | 
} 
 | 
  
 | 
int misc_write(struct udevice *dev, int offset, void *buf, int size) 
 | 
{ 
 | 
    const struct misc_ops *ops = device_get_ops(dev); 
 | 
  
 | 
    if (!ops->write) 
 | 
        return -ENOSYS; 
 | 
  
 | 
    return ops->write(dev, offset, buf, size); 
 | 
} 
 | 
  
 | 
int misc_ioctl(struct udevice *dev, unsigned long request, void *buf) 
 | 
{ 
 | 
    const struct misc_ops *ops = device_get_ops(dev); 
 | 
  
 | 
    if (!ops->ioctl) 
 | 
        return -ENOSYS; 
 | 
  
 | 
    return ops->ioctl(dev, request, buf); 
 | 
} 
 | 
  
 | 
int misc_call(struct udevice *dev, int msgid, void *tx_msg, int tx_size, 
 | 
          void *rx_msg, int rx_size) 
 | 
{ 
 | 
    const struct misc_ops *ops = device_get_ops(dev); 
 | 
  
 | 
    if (!ops->call) 
 | 
        return -ENOSYS; 
 | 
  
 | 
    return ops->call(dev, msgid, tx_msg, tx_size, rx_msg, rx_size); 
 | 
} 
 | 
  
 | 
struct udevice *misc_get_device_by_capability(u32 capability) 
 | 
{ 
 | 
    const struct misc_ops *ops; 
 | 
    struct udevice *dev; 
 | 
    struct uclass *uc; 
 | 
    int ret; 
 | 
    u32 cap; 
 | 
  
 | 
    ret = uclass_get(UCLASS_MISC, &uc); 
 | 
    if (ret) 
 | 
        return NULL; 
 | 
  
 | 
    for (uclass_first_device(UCLASS_MISC, &dev); 
 | 
         dev; 
 | 
         uclass_next_device(&dev)) { 
 | 
        ops = device_get_ops(dev); 
 | 
        if (!ops || !ops->ioctl) 
 | 
            continue; 
 | 
  
 | 
        ret = ops->ioctl(dev, IOCTL_REQ_CAPABILITY, &cap); 
 | 
        if (!ret && ((cap & capability) == capability)) 
 | 
            return dev; 
 | 
    } 
 | 
  
 | 
    return NULL; 
 | 
} 
 | 
  
 | 
UCLASS_DRIVER(misc) = { 
 | 
    .id        = UCLASS_MISC, 
 | 
    .name        = "misc", 
 | 
}; 
 |