162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * @File cthardware.c 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * @Brief 862306a36Sopenharmony_ci * This file contains the implementation of hardware access methord. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * @Author Liu Chun 1162306a36Sopenharmony_ci * @Date Jun 26 2008 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "cthardware.h" 1562306a36Sopenharmony_ci#include "cthw20k1.h" 1662306a36Sopenharmony_ci#include "cthw20k2.h" 1762306a36Sopenharmony_ci#include <linux/bug.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ciint create_hw_obj(struct pci_dev *pci, enum CHIPTYP chip_type, 2062306a36Sopenharmony_ci enum CTCARDS model, struct hw **rhw) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci int err; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci switch (chip_type) { 2562306a36Sopenharmony_ci case ATC20K1: 2662306a36Sopenharmony_ci err = create_20k1_hw_obj(rhw); 2762306a36Sopenharmony_ci break; 2862306a36Sopenharmony_ci case ATC20K2: 2962306a36Sopenharmony_ci err = create_20k2_hw_obj(rhw); 3062306a36Sopenharmony_ci break; 3162306a36Sopenharmony_ci default: 3262306a36Sopenharmony_ci err = -ENODEV; 3362306a36Sopenharmony_ci break; 3462306a36Sopenharmony_ci } 3562306a36Sopenharmony_ci if (err) 3662306a36Sopenharmony_ci return err; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci (*rhw)->pci = pci; 3962306a36Sopenharmony_ci (*rhw)->chip_type = chip_type; 4062306a36Sopenharmony_ci (*rhw)->model = model; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci return 0; 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ciint destroy_hw_obj(struct hw *hw) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci int err; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci switch (hw->pci->device) { 5062306a36Sopenharmony_ci case 0x0005: /* 20k1 device */ 5162306a36Sopenharmony_ci err = destroy_20k1_hw_obj(hw); 5262306a36Sopenharmony_ci break; 5362306a36Sopenharmony_ci case 0x000B: /* 20k2 device */ 5462306a36Sopenharmony_ci err = destroy_20k2_hw_obj(hw); 5562306a36Sopenharmony_ci break; 5662306a36Sopenharmony_ci default: 5762306a36Sopenharmony_ci err = -ENODEV; 5862306a36Sopenharmony_ci break; 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return err; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciunsigned int get_field(unsigned int data, unsigned int field) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci int i; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci if (WARN_ON(!field)) 6962306a36Sopenharmony_ci return 0; 7062306a36Sopenharmony_ci /* @field should always be greater than 0 */ 7162306a36Sopenharmony_ci for (i = 0; !(field & (1 << i)); ) 7262306a36Sopenharmony_ci i++; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci return (data & field) >> i; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_civoid set_field(unsigned int *data, unsigned int field, unsigned int value) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci int i; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci if (WARN_ON(!field)) 8262306a36Sopenharmony_ci return; 8362306a36Sopenharmony_ci /* @field should always be greater than 0 */ 8462306a36Sopenharmony_ci for (i = 0; !(field & (1 << i)); ) 8562306a36Sopenharmony_ci i++; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci *data = (*data & (~field)) | ((value << i) & field); 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 90